参照透過性とは何ですか?


285

参照の透明性という用語はどういう意味ですか?「イコールをイコールに置き換えることができる」という説明を聞いたことがありますが、これは不十分な説明のようです。


1
うわー、なぜこの質問の人気が急上昇したのか...
Claudiu

1
@claudia:確かには言えませんが、r / haskellは風を吹き、多くの人がUdayはかなり正確ではありますが、コミュニティで少しジャイブを取っていると感じました。
エフリー2012

6
@efreyジャイブ、おそらくそうだった。しかし、関数型プログラマーが命令型プログラミング言語や副作用のある関数型言語(LispやMLなど)を、それらが参照透過的ではないと主張して撃墜したとき、彼らはジャイブを取っていませんか?彼らはそうする前に少なくとも事実を正しく理解すべきではないのか?
Uday Reddy

2
@Claudiu Haskell Redditに投稿していて、Conalがツイートしています。ディスカッションは面白く、幅広い議論に値すると思った。ウダイのジャイブに注意を向け、議論を刺激した。私たちのFPersは時々自己満足して良い製品が必要になる場合があることに同意します。
chrisdornan 2012

7
@efrey。実際、それが私が2番目の投稿でBird and Wadler(意味論者?)から引用することを選択した理由です。知識豊富な人々は、参照の透明性の一般的な概念が曖昧で、おそらく一貫性がないことを知っています。しかし、それはプログラミングコミュニティに適切に説明されたことはありません。うまくいけば、ここでの私の執筆が変化をもたらすでしょう。
Uday Reddy

回答:


362

「参照の透明性」という用語は、論理と数学の方法に基づいて自然言語の構成要素、ステートメント、および引数を分析する哲学の分岐である分析哲学に由来します。言い換えれば、これはコンピュータサイエンス以外の分野で、プログラミング言語のセマンティクスと呼ばれるものに最も近い主題です。哲学者ウィラード・クインは、参照の透明性の概念の開始に責任がありましたが、それはまた、バートランド・ラッセルとアルフレッド・ホワイトヘッドのアプローチに暗示されていました。

基本的に、「参照の透明性」は非常にシンプルで明確なアイデアです。「リファレント」という用語は、分析哲学で、表現が参照するものについて話すために使用されます。これは、プログラミング言語のセマンティクスにおける「意味」または「表記」が意味するものとほぼ同じです。Andrew Birkettの例(ブログ投稿)を使用すると、「スコットランドの首都」という用語はエジンバラの都市を指します。これは「指示対象」の簡単な例です。

文中の文脈は、その文脈の用語を同じエンティティ参照する別の用語に置き換えても意味が変わらない場合、「参照的に透過的」です。例えば

スコットランド議会はスコットランドの首都で会合します。

と同じ意味

スコットランド議会がエディンバラで開催されます。

したがって、「スコットランド議会が会合する...」という文脈は、参照的に透明な文脈です。意味を変えることなく「スコットランドの首都」を「エジンバラ」に置き換えることができます。別の言い方をすれば、文脈はその用語が何を参照しているかにのみ注意を払い、他には何も注意しません。それは、文脈が「参照的に透明」であるという意味です。

一方、文では、

エディンバラは1999年からスコットランドの首都です。

そのような交換はできません。そうすると、「エジンバラは1999年からエジンバラになっている」という結果になってしまいます。これは言い過ぎですが、元の文と同じ意味を伝えていません。したがって、「1999年以来エディンバラは...」という文脈は、参照的に不透明である(参照的に透明の反対)ようです。それは明らかにその用語が指すものより何かに関心があります。それは何ですか?

「スコットランドの首都」のようなものは明確な用語と呼ばれ、論理学者や哲学者に長い間頭を痛めることはありませんでした。ラッセルとクインは、それらが実際には「参照」ではない、つまり、上記の例がエンティティの参照に使用されていると考えるのは誤りであると言ってそれらを分類しました。「1999年以来、エジンバラはスコットランドの首都でした」を理解する正しい方法は、

スコットランドには1999年以来首都があり、その首都はエディンバラです。

この文はくだらないものに変換することはできません。問題が解決しました!クインの要点は、自然言語は実際の使用に便利なように作られているため、乱雑であるか、少なくとも複雑であると言うことでしたが、哲学者や論理学者は正しい方法でそれらを理解することによって明快さをもたらす必要があります。参照の透明性は、そのような意味を明確にするために使用されるツールです。

これはすべてプログラミングと何の関係があるのでしょうか?それほどではありません。すでに述べたように、参照の透明性は、言語の理解、つまり意味の割り当てに使用されるツールです。 プログラミング言語のセマンティクスの分野を創設したクリストファー・ストラシェイは、意味の研究にそれを使用しました。彼の基礎論文「プログラミング言語の基本概念」がWebで入手可能です。それは美しい紙であり、誰でもそれを読んで理解することができます。だから、そうしてください。あなたは多くの悟りを開くでしょう。この段落では、「参照の透明性」という用語を紹介しています。

式の最も有用なプロパティの1つは、Quine参照透過性によって呼び出されるものです。本質的に、これは、部分式を含む式の値を見つけたい場合、部分式について知る必要があるのはその値だけであることを意味します。内部構造、コンポーネントの数と性質、それらが評価される順序、またはそれらが書き込まれるインクの色など、サブ式のその他の機能は、メイン式の値とは無関係です。式。

「本質的に」の使用は、Stracheyが簡単な言葉で説明するためにそれを言い換えていることを示唆しています。関数型プログラマーは、この段落を独自の方法で理解しているようです。この論文には、「参照の透明性」が他に9件ありますが、他の問題については気にしていないようです。実際、Stracheyの論文全体は、命令型プログラミング言語の意味を説明することに専念しています。しかし、今日、関数型プログラマーは、命令型プログラミング言語は参照に対して透過的ではないと主張してます。Stracheyは彼の墓を回しているでしょう。

私たちは状況を救うことができます。自然言語は実用に便利なように作られているので、「面倒、または少なくとも複雑」だと言いました。プログラミング言語も同じです。実用化に向けて作られているので、「面倒くさいか、少なくとも複雑」です。それは彼らが私たちを混乱させる必要があるという意味ではありません。意味が明確になるように、参照に対して透過的なメタ言語を使用して、正しい方法で理解する必要があります。私が引用した論文では、Stracheyがまさにそれを行っています。彼は命令型プログラミング言語の意味を、それらを基本概念に分解し、どこにも明快さを失うことなく説明しています。彼の分析の重要な部分は、プログラミング言語の式には2種類の「値」があることを指摘することです。r値。Stracheyの論文の前は、これは理解されておらず、混乱が最高を支配した。今日、Cの定義はそれを日常的に言及しており、すべてのCプログラマはその違いを理解しています。(他の言語のプログラマーも同じように理解しているかどうかはわかりません。)

クインとストレイチーはどちらも、何らかの形の文脈依存を伴う言語構造の意味に関心を持っていました。たとえば、「エジンバラは1999年以来スコットランドの首都でした」という例は、「スコットランドの首都」が考慮されている時期に依存しているという事実を示しています。このようなコンテキスト依存性は、自然言語とプログラミング言語の両方で現実です。関数型プログラミングでも、自由変数と束縛変数は、それらが出現するコンテキストに関して解釈されます。何らかの種類のコンテキスト依存は、何らかの方法で参照透過性をブロックします。依存する文脈に関係なく用語の意味を理解しようとすると、再び混乱に陥ります。クインはモーダルロジックの意味に関心を持っていました。彼はそれを保持しましたモーダルロジックは参照的に不透明であり、それを参照的に透明なフレームワークに変換することによってクリーンアップする必要があります(たとえば、必要性を証明可能性と見なすことによって)。彼はこの議論をほとんど失った。論理学者も哲学者も、クリプケの可能な世界の意味論は完全に適切であると考えました。同様の状況は、命令型プログラミングにも適用されます。Stracheyによって説明された状態依存性およびレイノルズによって説明された店舗依存性(クリプケの可能な世界の意味論と同様の方法で)は完全に適切です。関数型プログラマーはこの研究の多くを知りません。参照の透明性に関する彼らの考えは、大粒の塩でとられるべきです。

[補足:上記の例は、「スコットランドの首都」などの単純なフレーズには複数のレベルの意味があることを示しています。ある時点で、私たちは現時点で資本について話しているかもしれません。別のレベルでは、スコットランドが時間の経過を通じて持っていた可能性のあるすべての首都について話すかもしれません。通常の練習では、特定のコンテキストを「ズームイン」し、「ズームアウト」してすべてのコンテキストを非常に簡単に広げることができます。自然言語の効率は、そうする能力を利用しています。命令型プログラミング言語は、ほとんど同じ方法で効率的です。割り当て(r-value)の右側にある変数xを使用して、特定の状態でのその値について話すことができます。または、そのl値について話すかもしれませんすべての州にまたがっています。そのようなことに戸惑うことはめったにありません。ただし、言語構造に固有の意味のすべての層を正確に説明できる場合とできない場合があります。そのような意味のすべての層は必ずしも「明白」ではなく、それらを適切に研究することは科学の問題です。しかし、普通の人々がそのような階層化された意味を説明するのが無分別であることは、彼らがそれらについて混乱していることを意味しません。]

以下の別の「追記」は、この議論を関数型プログラミングと命令型プログラミングの懸念に関連付けています


10
感謝しますが、平等という「明白な」拡張概念があるとは思いません。「スコットランドの首都」がエディンバラの街を指すと言ったとき、あなたはそれについて二度と考えませんでした。しかし、「1999年以降」について話し始めたとき、あなたは突然時間が含まれていることに気づきました。したがって、平等の拡張概念は非常に微妙な場合があり、プログラミング言語の研究者によって正式化されています。延長平等を完全に理解したい人は、その研究の成果を学ぶ必要があります。それはまったく「自明」ではないかもしれません。
Uday Reddy

5
素晴らしい!RTに関するよくある誤解に対する歓迎の救済。たとえば、RTを機能に結び付ける。あるいは、(Wikipediaのように)式をその値で置き換えることで定義します。式と値は異なる種類のものであるため、奇妙なことにそうです。おそらく、命令型言語のRT-nessを検討する際に人々が失敗する1つの場所は、これらの「値」が、ストアの関数のようなより複雑なものではなく、数値のような単純なものであると想定することです。
Conal

13
@sclvコンピュータサイエンスに対する分析哲学の広範な影響については、私たちが知っているように、コンピュータサイエンスはGodel、Church、Kleene、およびTuringによって設立されたと言っておく必要があります。これらの人々は論理学者であり、論理学の数学的および哲学的側面の両方、特にペアーノ、フレーゲ、ラッセル、ホワイトヘッド、カーナップ、クインの伝統に精通しています。現代のコンピュータサイエンスの初期の開拓者たちは、そのつながりを知っていました。しかし、コンピュータサイエンスの急速な成長により、それらは深刻化しています。それらに戻る必要があります。
Uday Reddy、2012

5
@sclvロジックは伝統的に結果の科学として解釈されています。でももっと広いと思います。情報科学です。クイン、私はより広い視野をもたらした最初のものと思います。「単語とオブジェクト」は、自然言語ステートメントの情報内容の分析です。しかし、哲学者も数学者も、古くから文明と科学の中心的な計算がどのように行われているかを考えると、計算に積極的に関心を向けたことはありません。彼らに興味を持ってもらう方法を見つける必要があります。
Udayレディ

3
@Conal:私はあなたの主張を増幅する新しい答えを追加しました。それはおそらくページの下部にあります。
Udayレディ

134

関数型プログラミングで一般的に使用される用語である参照透過性は、関数と入力値が与えられた場合、常に同じ出力を受け取ることを意味します。つまり、関数で使用される外部状態はありません。

以下は、参照透過関数の例です。

int plusOne(int x)
{
  return x+1;
}

入力と関数が指定された参照透過関数を使用すると、関数を呼び出す代わりに、それを値に置き換えることができます。したがって、plusOneを5のパラメーターで呼び出す代わりに、6に置き換えることができます。

別の良い例は、一般的に数学です。関数と入力値が与えられた数学では、常に同じ出力値にマッピングされます。f(x)= x + 1.したがって、数学の関数は参照的に透過的です。

この概念は研究者にとって重要です。これは、参照透過的な関数がある場合に、簡単な自動並列化とキャッシングに役立つことを意味するためです。

参照透過性は常にHaskellのような関数型言語で使用されます。

-

対照的に、参照不透明性の概念があります。これは反対を意味します。関数を呼び出しても、常に同じ出力が生成されるとは限りません。

//global G
int G = 10;

int plusG(int x)
{//G can be modified externally returning different values.
  return x + G;
}

別の例は、オブジェクト指向プログラミング言語のメンバー関数です。メンバー関数は通常、そのメンバー変数を操作するため、参照は不透明になります。メンバー関数は、もちろん、参照に対して透過的です。

さらに別の例は、テキストファイルから読み取り、出力を印刷する関数です。この外部テキストファイルはいつでも変更される可能性があるため、関数は参照的に不透明になります。


1
ヘッドアップするだけで、参照的に透明なメンバー関数を使用して、完全に参照的に透明なオブジェクトを作成できます。okmij.org/ftp/Scheme/oop-in-fp.txtを
ジョナサン

1
そして、この記事で取り上げ
Jonathan Arkell

完全に参照透過的なクラスの場合、おそらくすべてのメンバー関数が静的になります。
ブライアンR.ボンディ

13
ここで話しているのは参照の透明性ではありませんが、一般にそのように呼ばれます。Udayの2つの回答とそのコメントをご覧ください。特に、「出力」と呼んでいるのは表示ではありません。「plusG 3」を同じ値/表記を持つ他の式に置き換えた場合、実際に同じ意味のプログラムが得られるため、RTは命令型言語で動作します。命令型言語での意味は「ストア」(状態)の関数であるため、「3 + 110 」または「13」という表現は「plusG 3」と同じ意味を持ちません
Conal

1
副作用と状態の変化に関する記事を読んだだけで、RTと関係があると直感しました。メモを追加していただけませんか?
Gaurav、2015

91

参照透過関数は、その入力にのみ依存する関数です。


4
オブジェクトが状態を持つため、オブジェクト指向プログラミングでは難しいのはこのためです。
クリス

5
それで、関数を説明するとき、「参照的に透明」は「決定論的」と同一であると言うのは正しいですか?そうでない場合、2つの用語の違いは何ですか?
mwolfe02

1
これは、「純粋な」関数の定義のようにも聞こえます。
Evgeny A.

75

[これは、議論を関数型/命令型プログラミングの懸念に近づけるための、3月25日からの私の回答の追記です。]

関数型プログラマーの参照透過性の考え方は、次の3つの点で標準の概念とは異なるようです。

  • 哲学者/論理学者は、「参照」、「表記」、「designatum」、「bedeutung」(フリージのドイツ語の用語)などの用語を使用しますが、関数型プログラマは「値」という用語を使用します。(これは完全に彼らのしていることではありません。ランディン、ストレイチー、およびその子孫も参照/表示について話すために「値」という用語を使用したことに気づきます。素朴な方法で使用すると大きな違いがあります。)

  • 関数型プログラマーは、これらの「値」はプログラミング言語の内部ではなく外部に存在すると信じているようです。これを行うことで、彼らは哲学者やプログラミング言語の意味論者の両方とは異なります。

  • 彼らはこれらの「価値」は評価によって得られることになっていると信じているようです。

たとえば、参照の透明性に関するウィキペディアの記事によると、今朝は次のようになります。

プログラムの動作を変更せずに式をその値に置き換えることができる(つまり、同じ入力で同じ効果と出力を持つプログラムを生成する)場合、その式は参照上透過的であるといいます。

これは、哲学者/論理学者の発言とは完全に異なります。彼らは、そのコンテキスト内のを、同じものを参照する別の相互参照式)で置き換えることができる場合、そのコンテキストは参照または参照上透過的であると言います。これらの哲学者/論理学者は誰ですか?彼らはフレゲラッセルホワイトヘッドカルナップクイン教会を含みますそして無数の他。それぞれがそびえ立つ人物です。これらの論理学者の組み合わされた知的力は、控えめに言っても地球を破壊するものです。それらのすべては、指示対象/表示が正式な言語の外に存在し、言語内の表現がそれらについて話すことができるだけであるという立場では全会一致です。したがって、言語内で実行できることは、1つの式を、同じエンティティを参照する別の式に置き換えることだけです。指示対象/表示自体言語内に存在しません。関数型プログラマーがこの確立された伝統から逸脱するのはなぜですか?

プログラミング言語の意味論者がそれらを誤解させたかもしれないと推測するかもしれません。しかし、そうではありませんでした。

Landin

(a)各式は入れ子の部分式構造を持ちます、(b)各部分式 は何か(通常は数値、真理値または数値関数)を示します。(c)式が示すもの、つまり「値」は、それらの他のプロパティではなく、そのサブ式の値。[強調を追加]

ストイ

式に関して重要なのはその値だけであり、任意の部分式は、値が同じである他の式で置き換えることができます [追加の強調]。さらに、式の値は、特定の制限内で、それが発生するときは常に同じです。」

鳥とワドラー

式の値は、その構成式(存在する場合)の値にのみ依存し、これらの部分式は、同じ値を持つ他のものと自由に置き換えることができます [追加の強調]。

したがって、振り返ってみると、「参照」/「表示」を「値」に置き換えることで用語を簡略化するランディンとストラシェイの努力は賢明ではなかったかもしれません。「価値」を聞くとすぐに、それにつながる評価プロセスを考えたくなる誘惑があります。それが意味ではないことがはっきりしているかもしれませんが、評価が「価値」として生み出すものを考えるのも同様に魅力的です。関数型プログラマーの目には、「参照の透明性」という概念があったと私が収集したものです。しかし、初期の意味論者によって話されていた「価値」は、評価や関数の出力やそのようなものの結果ではありません。用語の意味です。

表現のいわゆる「値」(古典的な哲学者の言説における「参照」または「表記」)を複雑な数学的/概念的なオブジェクトとして理解すると、あらゆる種類の可能性が開かれます。

  • Stracheyは命令型プログラミング言語の変数をL値として解釈しました。これは、3月25日の回答で述べたように、プログラミング言語の構文内で直接表現されない洗練された概念的なオブジェクトです。
  • 彼はまた、状態間関数、構文内の「値」ではない複雑な数学オブジェクトの別のインスタンスなどの言語でコマンドを解釈しました。
  • Cの副作用のある関数呼び出しでさえ、状態を状態と値のペアにマップする状態変換として明確に定義された「値」があります(関数型プログラマーの用語では、いわゆる「モナド」)。

関数型プログラマーがそのような言語を「参照透過」と呼ぶことに抵抗があるということは、そのような複雑な数学的/概念的なオブジェクトを「値」として認めることに消極的であることを単に意味します。一方、彼らはそれが彼ら自身の好きな構文に入れられて「モナド」のような流行語でドレスアップされているとき、状態トランスフォーマーを「値」と呼ぶことを完全に喜んでいるようです。「参照の透明性」についての彼らの考えには一貫性があると彼らに認めたとしても、彼らは完全に矛盾していると言わざるを得ません。

少しの歴史は、これらの混乱がどのようにして生じたのかについていくつかの光を投げるかもしれません。1962年から1967年までの期間は、クリストファー・ストラシェにとって非常に集中的な期間でした。1962年から65年の間、モーリスウィルクスのリサーチアシスタントとしてアルバイトをし、CPLとして知られるようになったプログラミング言語を設計および実装しました。これは命令型プログラミング言語でしたが、強力な関数型プログラミング言語機能も備えることを目的としています。Strainyのコンサルタント会社の従業員であったLandinは、Stracheyのプログラミング言語の見方に大きな影響を与えました。ランドマークは、1965年の画期的な論文「Next 700プログラミング言語」で、関数型プログラミング言語を宣伝している(それらを代表的なものと呼ぶ)言語)、そして命令型プログラミング言語を「アンチテーゼ」として説明します。その後の議論では、StracheyがLandinの強い地位に疑問を投げかけているのがわかります。

... DLはすべての言語のサブセットを形成します。これらは興味深いサブセットですが、慣れていないと使いにくいものです。現時点では、命令とジャンプを含む言語で証明を構築する方法がわからないためそれらが必要です。[強調を追加]

1965年、Stracheyはオックスフォードでリーダーの地位に就き、命令とジャンプの理論の開発に本質的にフルタイムで取り組んできたようです。1967年までに、彼はコペンハーゲンのサマースクールで「プログラミング言語の基本的な概念」に関するコースで教えた理論の準備が整いました。講義ノートは公開されるはずだったが、「残念ながら、拡張編集のため、議事録は具体化されなかった。ただし、オックスフォードでのStracheyの仕事の多くと同様に、この論文には影響力のある民間の回覧があった」。(マーティンキャンベルケリー

Stracheyの著作を入手するのが困難なため、人々は二次的な情報源や伝聞に頼り、混乱が広がっていた可能性があります。しかし、「基本概念」がWebですぐに利用できるようになったので、推測作業に頼る必要はありません。私たちはそれを読んで、Stracheyが何を意味するかについて私たち自身の決心をする必要があります。特に:

  • セクション3.2では、彼は「式」を扱い、「R値の参照の透明性」について語っています。
  • 彼のセクション3.3は「コマンド」を扱っており、「L値の参照透過性」について語っています。
  • セクション3.4.5で彼は「関数とルーチン」について語り、「R値コンテキストでのR値の参照透過性の逸脱は、式をいくつかのコマンドとより単純な式に分解することによって排除する必要があるか、またはこれは難しいことが判明し、コメントの対象となりました。」

L値、R値、および命令型プログラマーの概念的宇宙に存在するその他の複雑なオブジェクトの違いを理解しない「参照透過性」についての話は、根本的に誤解されています。


10
これらの2つの「値」の概念(評価と表記)を混同すると、概念間のギャップが大きい命令型言語に対する批判において、関数型プログラマーが誤解を招くので、強調する価値があると思います。
Conal

8
つまり、評価の概念は、命令型言語はRTではないが、表記の概念はRTではないという結論につながります。
Conal

12
言語の表示セマンティクスを完全に掘り下げたら、参照を透過的にするしかありません。したがって、これはプログラミング言語に関してはこの用語は役に立たないということと同じです。
トムクロケット

20
だから、人々は過去にその用語を使用したときに他の人々が意味したものとは実質的に異なる何かを意味する用語を使用する癖があるようです。私が言うには:英語へようこそ。
Daniel Pratt、

17
@DanielPratt:副作用のない自由が関数型プログラマーが意味したいものであるなら、なぜそれを「参照透過性」と呼ぶのですか?彼らはそれを「副作用のない自由」と呼ぶことができます。これは完全に明確な考えです。「副作用のないこと」が何を意味するのかをstackexchangeで尋ねる必要はありません。誰も理解していないように思われる壮大な古典的な用語を盗用する必要はどこにありますか?
Udayレディ

23

アルゴリズムを変更せずに式をその値で置き換えることができる場合、式は参照透過的であり、同じ入力で同じ効果と出力を持つアルゴリズムを生成します。


18

参照透過関数は、数学関数のように機能する関数です。同じ入力が与えられると、常に同じ出力が生成されます。これは、渡された状態が変更されておらず、関数に独自の状態がないことを意味します。


10

簡潔な説明が必要な場合は、危険を冒します(ただし、以下の開示を読んでください)。

プログラミング言語の参照の透明性は、方程式の推論を促進します。参照の透明性が高いほど、方程式の推論を実行するのが簡単になります。たとえば、(疑似)関数定義がある場合、

fx = x + x、

この定義のスコープ内でf(foo)をfoo + fooに(安全に)置換できる容易さは、この削減を実行できる場所にあまり多くの制約を課すことなく、プログラミング言語の参照透過性の程度を示す良い指標です持っています。

たとえば、fooがCプログラミングの意味でx ++である場合、この削減を安全に実行することはできません(つまり、この削減を実行すると、最初と同じプログラムになってしまいます)。

実用的なプログラミング言語では、完全な参照の透明性はわかりませんが、関数型プログラマーはほとんどの場合よりもそれを気にします(Haskellを参照してください。

(完全な開示:私は関数型プログラマーなので、トップの回答までに、この説明を細かく理解する必要があります。)


3
方程式の推論を容易にする言語については問題ありません。しかし、私はそれが古典的に定義されている「参照の透明性」と関係があることに異議を唱えます。次に、実用的なプログラマーとして、方程式の推論は過大評価されていると思います。実際に重要な推論は、事前条件、事後条件、不変条件、およびデータ抽象化に関係しています。このような推論手法に依存している人にとって、副作用はあまり問題にならないと思われます。したがって、式の副作用は悪い考えだと私はあなたに同意しますが、それらは致命的な議論を表すようには見えません。
Udayレディ

1
@UdayReddy関数プログラマがプログラムの参照透過性をダイヤルアップする特定の方法を選択した(副作用を排除し、プログラムの洗練された強力な代数を開発した)か、おそらく参照透過性を理解していない実践者がいるため彼らはそうしていると考えていますが、関数型プログラミング言語が参照の透明性を高めることができない、または関数型言語のプログラマーやコンパイラー作成者がこの形式的な扱いやすさの向上を多くの目的に活用していないという意味ではありません。
クリスドルナン

2
Chris:Udayは、Stracheyがプログラミング言語のセマンティクス、特に命令型言語の参照の不透明性の問題を解消したと指摘しました。したがって、関数型プログラマーは、「プログラムの参照の透明性を向上させる」ことはできません。具体的な例として、RTのヘルプが必要ないため、Haskell IOはRTの助けにはなりません。
Conal

2
@chrisdornan:上記の最初のコメントには申し訳ありません。私自身、最初の2つの文で何を言おうとしているかを理解するのに苦労しました:-(しかし、ここでは説明を示します。2レベルまたはマルチレベルのステージング計算を考えてみてください。各ステージング演算子は参照的に不透明です。実際には。。、、各参照上の不透明なオペレータは、等式推論のための境界を引用オペレータしかし、あなたは完全に罰金、各ステージ内等式推論を行うことができますので、セットアップしかし、あなたはまだ、これらの境界内に等式推論を持っている。。
ウダイレディ

1
@chrisdomain:さらに、このようなステージングオペレーターを追放するために、参照の透明性-純粋主義者になりたい人はほとんどいません。これらの演算子は非常に便利です。ステージングを手動で行うことによるそれらなしのプログラミングは、退屈でエラーが発生しやすく、見苦しいでしょう。また、ステージングを手動で行っても、以前よりも同等の推論を購入することはできません。したがって、純粋な方程式の推論を追求する上で優れたプログラミングデバイスを禁止することは、顔をせがむために鼻を切るようなものです。
Uday Reddy

8

語源に興味がある場合(つまり、この概念にこの特定の名前があるのはなぜですか)、このトピックに関する私のブログ投稿をご覧ください。用語は、哲学者/論理学者のクインから来ています。


4
  1. Denotational-semanticsは、分母のを構成するドメインを構築することによる言語のモデリングに基づいています
  2. 関数型プログラマは、という用語を使用して、言語の書き換えルールに基づく計算の収束を説明します。その運用上のセマンティクス。

1には、問題の2つの言語が明確に示されています。

  • モデル化されるもの、オブジェクト言語
  • モデリングの言語、メタ言語

2では、オブジェクトとメタ言語の近さのおかげで、混乱する可能性があります。

言語の実装者として、私はこの違いを常に覚えておく必要があることに気づきました。

だからレディ教授はあなたをこのように言い換えることができます:-)

関数型プログラミングとセマンティクスのコンテキストでは、参照透過性という用語は参照透過的ではありません。


1
ははは。説明ありがとう。問題は、関数型プログラマーがすべてのプログラミング言語に適用できる「参照透過性」の一般的な概念を持っているかのように振る舞うことでもあります。しかし、これは彼らの「価値」の概念に依存しており、それは他の言語では意味をなさないかもしれません。「参照の透明性」の一般理論を主張するには、一般理論の「価値」を生み出す必要があります。それは今のところ欠けています。
Udayレディ

4

次の回答は、物議を醸している第1と第3の回答に追加し、それらを修飾するものです。

式が指示対象を示すか、または参照することを認めましょう。ただし、問題は、これらの指示対象が式自体の一部として同形にエンコードされ、そのような式を「値」と呼ぶことができるかどうかです。たとえば、リテラル数値は一連の算術式のサブセット、真理値は一連のブール式のサブセットなどです。アイデアは、式をその値に評価することです(ある場合)。したがって、「値」という語は、表記または一連の式の区別された要素を指す場合があります。しかし、指示対象と値の間に同型性(全単射)がある場合、それらは同じものであると言えます。(これは、指示意味論の分野で証明されているように、指示対象と同型を定義するように注意する必要があります。3番目の回答への返信で言及された例を示すには、data Nat = Zero | Suc Nat 予想どおり自然数のセットに対応していません。)

E[·]いくつかの四半期では「コンテキスト」としても知られる、穴のある式を書いてみましょう。Cのような式の2つのコンテキスト例は[·]+1、および [·]++です。

[[·]]式(穴のないもの)を取り、その意味(参照、表示など)を意味のある宇宙に提供する関数を書いてみましょう。(私は表記セマンティクスの分野から表記を借りています。)

次のように、Quineの定義をいくぶん形式的に適用してみましょう。コンテキストE[·] は、2つの式E1E2(そこに穴がない)が与えられた場合[[E1]] = [[E2]](つまり、式が同じ参照先を示す/参照する場合)は参照的に透過的であり、その場合[[E[E1]]] = [[E[E2]]](つまり、塗りつぶし) - E1またはのいずれかを含む穴でE2、同じ指示対象も表す式になります)。

等号を等号に置き換えるというライプニッツの規則は、通常、「if E1 = E2then E[E1] = E[E2]」として表され 、これはE[·]関数であることを示しています。関数(またはその関数を計算するプログラム)はソースからターゲットへのマッピングであるため、各ソース要素に対して最大で1つのターゲット要素が存在します。非決定論的な関数は誤称であり、関係、集合を提供する関数などのいずれかです。ライプニッツのルールで等式=が表示である場合、二重括弧は単に付与され、省略されていると見なされます。したがって、参照透過的なコンテキストは関数です。ライプニッツの法則は方程式の推論の主要な要素であるため、方程式の推論は参照の透明性に明確に関連しています。

[[·]]denotationsの式から関数であり、それは式の制限されたサブセットとして理解「値」に表現から機能することができ、[[·]]評価として理解することができます。

さて、if E1が式でE2あり、値である場合、式、値、および評価の観点から参照の透明性を定義するときに、ほとんどの人が意味するものだと思います。しかし、このページの1番目と3番目の回答に示されているように、これは不正確な定義です。

などのコンテキストの問題[·]++は副作用ではありませんが、その値はCで同義的にその意味に定義されていません。関数は値ではありません(まあ、関数へのポインタはそうです)が、関数型プログラミング言語ではそうです。Landin、Strachey、および表示セマンティクスのパイオニアは、機能的な世界を使用して意味を提供することに非常に優れていました。

命令型Cライク言語の場合、関数を使用して式にセマンティクスを(大まかに)提供できます[[·]] : Expression -> (State -> State x Value)

ValueのサブセットですExpressionStateペア(識別子、値)を含みます。セマンティック関数は式を取り、その意味として、現在の状態から更新された状態と値のペアへの関数を提供します。たとえば、[[x]]は、現在の状態から、最初のコンポーネントが現在の状態で、2番目のコンポーネントがxの値であるペアへの関数です。対照的に、[[x++]]は現在の状態から、最初の成分がxの値が増加する状態であり、2番目の成分がまさにその値であるペアへの関数です。この意味で、コンテキスト[·]++は、上記の定義を満たしていれば、参照的に透過的です。

関数型プログラマーは[[·]]、式から値に関数として自然に回復するという意味で、参照透過性を使用する資格があると思います。関数はファーストクラスの値であり、状態は表示ではなく値でもかまいません。状態モナドは、(部分的に)状態を渡す(またはスレッド化する)ためのクリーンなメカニズムです。


おそらく「1番目」と「3番目」の回答は、それぞれUdayReddyの「3月25日」と「追記」の回答です。序数は、SOで回答を参照する良い方法ではありません。投票と承認は時間の経過とともに変化するだけでなく、複数の選択可能な順序があります。
philipxy

2

この「意味」の概念は、観察者の心の中で起こるものであることに注意してください。したがって、同じ「参照」は、人によって異なることを意味します。たとえば、ウィキペディアにエジンバラの曖昧性解消ページがあります。

プログラミングのコンテキストで現れる可能性がある関連する問題は、多態性かもしれません。

そして、多型の特殊なケース(またはおそらくキャスト)の名前を付ける必要があるかもしれません。私たちの目的のために、異なる多型のケースは、意味的に同等です(単に類似しているのではなく)。たとえば、1という数字は、整数型、複合型、またはその他のさまざまな型のいずれかを使用します-多態的に処理できます)。


0

コンピュータプログラムの構造と実装」(ウィザードブック)の参照透過性の定義は、割り当て操作の導入によって参照透過性がどのように違反されるかを説明することで補足されるため、役に立ちました。このテーマについて私が作成した次のスライドデッキを確認してください。 icic-in-sicp-the-wizard-book


0

参照の透明性は、次のように簡単に説明できます。

  • どのコンテキストでも常に同じ結果に評価される式[1]
  • 関数は、同じパラメーターを2回指定した場合、同じ結果を2回生成する必要があります[2]

たとえば、プログラミング言語Haskellは純粋な関数型言語です。つまり、参照が透過的です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.