カリーハワード同型から生じる最も興味深い等価物は何ですか?


97

私はカレーハワード同型に出会ったのは、プログラミングの人生の比較的遅い時期でした。おそらく、これが私を完全に魅了する一因となっています。これは、すべてのプログラミング概念について、形式論理には正確な類似物が存在することを意味し、その逆も同様です。ここにそのような類推の「基本的な」リストがあります。

program/definition        | proof
type/declaration          | proposition
inhabited type            | theorem/lemma
function                  | implication
function argument         | hypothesis/antecedent
function result           | conclusion/consequent
function application      | modus ponens
recursion                 | induction
identity function         | tautology
non-terminating function  | absurdity/contradiction
tuple                     | conjunction (and)
disjoint union            | disjunction (or)          -- corrected by Antal S-Z
parametric polymorphism   | universal quantification

だから、私の質問に:この同型のより興味深い/あいまいな含意のいくつかは何ですか?私は論理学者ではないので、このリストで表面をなぞっただけだと確信しています。

たとえば、ここでは、ロジック内の簡潔な名前を知らないプログラミングの概念をいくつか示します。

currying                  | "((a & b) => c) iff (a => (b => c))"
scope                     | "known theory + hypotheses"

そして、これは私がプログラミング用語で完全に固定していないいくつかの論理的な概念です:

primitive type?           | axiom
set of valid programs?    | theory

編集:

以下は、応答から収集されたいくつかの同等性です。

function composition      | syllogism                -- from Apocalisp
continuation-passing      | double negation          -- from camccann

閉鎖〜=公理のセット
Apocalisp

+1この質問とすべての質の高い回答とコメントは、インターネットを通じて学んだことよりもCHIについて多くを教えてくれました。
Alexandre C.

24
@ポール・ネイサン:goto | jumping to conclusions
ジョーイ・アダムス

すべての有効なプログラムのセットがモデルに
Daniil

1
fst / snd | 結合除去、左/右| 分離の導入
Tony Morris

回答:


33

あなたが最も興味深く、あいまいなものを明示的に求めたので:

CHを多くの興味深いロジックおよびロジックの定式化に拡張して、非常に多様な対応を取得できます。ここでは、あいまいなものではなく、いくつかのより興味深いものに加え、まだ出ていないいくつかの基本的なものに焦点を当てようとしました。

evaluation             | proof normalisation/cut-elimination
variable               | assumption
S K combinators        | axiomatic formulation of logic   
pattern matching       | left-sequent rules 
subtyping              | implicit entailment (not reflected in expressions)
intersection types     | implicit conjunction
union types            | implicit disjunction
open code              | temporal next
closed code            | necessity
effects                | possibility
reachable state        | possible world
monadic metalanguage   | lax logic
non-termination        | truth in an unobservable possible world
distributed programs   | modal logic S5/Hybrid logic
meta variables         | modal assumptions
explicit substitutions | contextual modal necessity
pi-calculus            | linear logic

編集:CHの拡張機能について詳しく知りたい人におすすめのリファレンス:

「モーダルロジックの判断による再構築」http://www.cs.cmu.edu/~fp/papers/mscs00.pdf-第一原理から始まり、その多くは非論理学者/言語理論家がアクセスできます。(ただし、私は2人目の著者なので、偏っています。)


いくつかのささいな例を提供してくれてありがとう(それは本当に元の質問の精神でした)、これらのいくつかは頭の中にあることを認めますが、「必要性」と「可能性」という用語はロジックで正確に定義されていますか?彼らはどのように同等の計算に変換しますか?
トムクロケット

2
これらのそれぞれについて公開された論文を指すことができるので、正確に定義されます。モーダルロジックはよく研究されており(アリストテレス以降)、さまざまな真実のモードに関連しています。「Aは必ず真である」は「可能なすべての世界でAが真である」を意味し、「Aはおそらく真である」は「Aは1つの可能な世界で真である」を意味します。「(必要に応じて(A-> B)そしておそらくA)->おそらくB」のようなことを証明することができます。モーダル推論規則は、CHでの通常のように、式の構成、型付け、および縮約規則を直接生成します。参照:en.wikipedia.org/wiki/Modal_logicおよびcs.cmu.edu/~fp/papers/mscs00.pdf
RD1

2
@pelotom:他の種類のロジックについて少し読みたくなるかもしれません。単純な古典的論理は、このコンテキストでは役に立たないことがよくあります。答えで直観主義論理に言及しましたが、モーダルおよび線形論理は「奇妙」であるだけでなく、本当に素晴らしいです。
CAマッキャン2010

1
ポインタをありがとう、私にはやるべきことがいくつかあるようです!
トムクロケット

2
@ RD1:あなたはそれが悪いと思います、私はHaskellで考えるのに多くの時間を費やしたので、意味のある前に述語論理の式を型シグネチャに精神的に変換しなければなりません。:(除外真ん中と、このような開始の法律は本当に混乱し、多分疑わしいように見えるしていることは言うまでもありません。
CAマッキャンに

26

あなたは非終了に関して少し物事を濁らせています。偽性は無人の型で表されます。最初に評価する型がないため、定義によって非終端にすることはできません。

非終了は矛盾を表します- 一貫性のないロジックです。一貫性のないロジックはもちろん、偽りを含む何でも証明することを可能にします

型のシステムは通常、矛盾を無視して直観主義的なロジックに対応し、必然的に構成主義者になります。つまり、古典的なロジックの特定の部分を直接表現することはできません。一方、型が有効な構成証明である場合、その型の用語はの存在を証明したものを構成する手段であるため、これは便利です。

構成主義フレーバーの主な特徴は、二重否定は非否定と同等ではないということです。実際、否定は型システムではほとんど原始的ではないので、代わりに、それが偽にnot Pなることを意味するものとして表すことができP -> Falsityます。したがって、二重否定はtypeを持つ関数であり(P -> Falsity) -> Falsity、これは明らかにtypeの何かと同等ではありませんP

しかし、これには興味深いひねりがあります!パラメトリック多態性を持つ言語では、型変数は無人のものを含むすべての可能な型に及ぶため、∀a. aある意味では完全に多態性の型は、ある意味ではほとんど偽です。では、ポリモーフィズムを使用して二重のほぼ否定を書くとどうなるでしょうか。次のようなタイプが得られます∀a. (P -> a) -> a。それはタイプの何かと同等Pですか?確かにそれは、それを恒等関数に適用するだけです。

しかし、ポイントは何ですか?なぜそのようなタイプを書くのですか?それはプログラミング用語で何か意味がありますか?まあ、それはすでにPどこかに型の何かを持っている関数と考えることができ、それをP引数として受け取る関数を与える必要があり、全体が最終的な結果型では多態的です。ある意味で、それは中断された計算を表し、残りが提供されるのを待っています。この意味で、これらの中断された計算は、一緒に構成したり、渡したり、呼び出したりすることができます。これは、SchemeやRubyなどの一部の言語のファンには馴染みのあるものになり始めます。これは、二重否定が継続渡しのスタイルに対応しているためです。、そして実際に上記で示した型は、まさにHaskellの継続モナドです。


訂正していただき、ありがとうございます。私は「偽り」を非終了の同義語として削除しました。二重否定<=> CPSの場合は+1!
トムクロケット

¬pをとして表す背後にある直感がよくわかりませんP -> Falsity。なぜ機能するのかはわかりますが(¬p≡p→⊥)、コードバージョンがわかりません。 P -> ⊥そうPでないときに正確に居住すべきですよね?しかし、この機能は常に存在している必要はありませんか?または、実際には決してできません。?のインスタンスを返すことができないからです。私はそれの条件をよく見ていません。ここの直感は何ですか?
Antal Spector-Zabusky

1
@Antal SZ:もちろん、直観は直観的な論理です!しかし、そうです、実際にそのような関数を書くことは困難です。あなたのプロファイルでHaskellを知っているようですが、多分代数的データ型とパターンマッチングについて考えているのでしょうか。無人型にはコンストラクタなく、したがってパターンマッチングの対象にはならないことを考慮してください。ボディのない「関数」を作成する必要がありますが、これはHaskellの合法ではありません。実際、私の知る限り、実行時の例外または非終了を使用せずにHaskellで否定型の項を記述する方法はありません。
CA McCann

1
@Antal SZ:一方、同等のロジックが一貫している場合、すべての関数は合計でなければなりません。たとえば、すべてのパターンマッチングは完全でなければなりません。したがって、パターンのない関数を書くためには、パラメーター型はコンストラクターを持たない、例えば無人である必要があります。したがって、そのような関数は合法的であり、したがって、その固有の型が存在するのは正確であり、その引数が無人の場合に限られます。したがって、関数P -> FalsityPfalse と同等です。
CA McCann

ああ、わかったと思います。私が楽しんでいたバージョンはのようなものでしたがf x = x、それはインスタンス化できる場合には異なりますがP = ⊥、それは明らかに一般的ではありませんでした。つまり、価値のない型を返すためには、本体は必要ないという考え方です。しかし、関数が定義可能で完全であるためには、ケースは必要ありません。したがって、P無人の場合、すべてがうまくいきますか?それは少し不安定ですが、私はそれを見ると思います。それはXorタイプの私の定義とかなり奇妙に相互作用するようです…私はそれについて考えなければならないでしょう。ありがとう!
Antal Spector-Zabusky

15

あなたのチャートは完全に正しくありません。多くの場合、タイプと用語を混同しています。

function type              implication
function                   proof of implication
function argument          proof of hypothesis
function result            proof of conclusion
function application RULE  modus ponens
recursion                  n/a [1]
structural induction       fold (foldr for lists)
mathematical induction     fold for naturals (data N = Z | S N)
identity function          proof of A -> A, for all A
non-terminating function   n/a [2]
tuple                      normal proof of conjunction
sum                        disjunction
n/a [3]                    first-order universal quantification
parametric polymorphism    second-order universal quantification
currying                   (A,B) -> C -||- A -> (B -> C), for all A,B,C
primitive type             axiom
types of typeable terms    theory
function composition       syllogism
substitution               cut rule
value                      normal proof

[1]チューリング完全関数型言語のロジックに一貫性がありません。再帰は、一貫した理論では対応していません。一貫性のないロジック/不健全な証明理論では、それを不一致/不健全を引き起こすルールと呼ぶことができます。

[2]繰り返しますが、これは完全性の結果です。ロジックが一貫している場合、これは反定理の証明になります-したがって、それは存在できません。

[3]関数型言語には存在しません。1次の論理的特徴を排除するためです。すべての定量化とパラメーター化は、数式で行われます。あなたは一次機能を持っていた場合は、より親切他があるだろう** -> *等。言説の領域の要素の種類。たとえば、in Father(X,Y) :- Parent(X,Y), Male(X)XおよびY談話のドメイン(と呼ぶDom)の範囲、およびMale :: Dom -> *


[1]-はい、もっと具体的になるべきだった。制約のない再帰ではなく、「構造的再帰」を意味しました。これは「フォールド」と同じだと思います。[3]-依存型付けされた言語で存在します
Tom Crockett、

[1]事実は、再帰関数呼び出し(モーダスポネン)によってプログラムが非終了にならない場合、呼び出しまたは環境に与えられるパラメーター(仮説)は、それらの呼び出し間で異なる必要があることです。したがって、再帰は同じ定理を複数回適用するだけです。特別なことがある場合、それは通常、数値の増加/減少(帰納的ステップ)であり、既存のケース(ベースケース)とのチェックです。これは、ロジックの数学的な帰納に対応しています。
Earth Engine

このチャートは本当に気に入っていますが、「n / a」とは言いません。終了するプログラムが唯一の種類のプログラムではないのと同じように、一貫性のあるロジックが唯一の種類のロジックではないからです。非終了関数は「循環引数」に対応し、カリーハワード同型の優れた例です。循環引数に「従う」と、無限ループに陥ります。
Joey Adams


13

私はこの質問が本当に好きです。私は多くのことを知りませんが、私はいくつかのことを持っています(Wikipediaの記事を参考にしてください、そこにはいくつかのきちんとしたテーブルなどがあります):

  1. 和の型/和集合の型(例えば data Either a b = Left a | Right b)は包含的選言と同等だと思います。そして、私はカレーハワードに精通していませんが、これはそれを実証していると思います。次の関数を考えます。

    andImpliesOr :: (a,b) -> Either a b
    andImpliesOr (a,_) = Left a
    

    私が正しく物事を理解していれば、タイプは、(言う ∧の  B)→( ★  B ★はどちらか、どちらか含むか含まないか、どこ、)と定義は、これが真実であることを述べている表します。あなたは排他的論理和を表している、⊕; しかしながら、( ∧  B)↛( ⊕  B)。たとえば、⊤∧⊤≡⊤ですが、⊤⊕⊥≡⊥、および⊤↛⊥です。つまり、abの両方が真である場合、仮説は真ですが、結論は偽です。したがって、この含意は偽でなければなりません。しかし、明らかに、( ∧  B)→( ∨ EitherEitherb)、abの両方がtrueの場合、少なくとも1つがtrueであるため。したがって、差別された組合が何らかの形の分離である場合、それらは包括的多様性でなければならない。これは証拠としては成り立つと思いますが、この概念を私に乱用しないでください。

  2. 同様に、アイデンティティ関数および非終了関数としてのトートロジーと不条理の定義はそれぞれ少しずれています。真の式は、ユニットタイプで表されます。これは、要素が1つしかないタイプdata ⊤ = ⊤です(;多くの場合、綴られ()ているかUnit、関数型プログラミング言語で使用されています)。これは理にかなっています。そのタイプが居住することが保証されているため、および居住者の可能性が1つしかないため、それは真でなければなりません。恒等関数は、単にa  →  aある特定のトートロジーを表します。

    非終了関数についてのコメントは、正確には何を意味するかによって異なりますが、もっと離れています。カリーハワードは型システムで機能しますが、非終了はそこでエンコードされません。Wikipediaによると、非終了を処理することは問題です。これを追加すると一貫性のないロジックが生成されるためです(たとえばwrong :: a -> bによって定義できるため、任意のaおよびbに対してa  →  bwrong x = wrong xあることを「証明」できます)。これが「不条理」によってあなたが意味したものであるなら、あなたは正確です。代わりに偽のステートメントを意味する場合、代わりに必要なのは無人のタイプです。たとえばdata ⊥-つまり、データを構築する方法のないデータ型です。これにより、値がまったくないため、無人である必要があり、falseと同等です。a -> b非終了関数を禁止する場合、これも無人であるので、おそらくを使用することもできると思いますが、100%確実ではありません。

  3. ウィキペディアによると、公理は、カリーハワードの解釈方法に応じて、コンビネーターまたは変数のいずれかで、2つの異なる方法でエンコードされます。Combinatorビューは、与えられたプリミティブ関数が、デフォルトで言えることをエンコードすることを意味すると思います(関数の適用はプリミティブであるため、モーダスポネンが公理であるのと同様です)。そして、私は考えて変数ビューは実際には同じこと-コンビネータを意味するかもしれないことを、すべての後に、特定の機能しているだけのグローバル変数です。プリミティブ型については、私がこれについて正しく考えていれば、プリミティブ型はエンティティ、つまり私たちが証明しようとしているプリミティブオブジェクトであると思います。

  4. 私のロジックと意味クラス、という事実によるもの( ∧  B)→  C  ≡  A  →(B  →  C)(そしてまた、そのB  →(A  →  C))、輸出等価の法則と呼ばれる自然演繹で少なくとも証明。カレーしているだけだと気づかなかったのですが、かっこいいので食べたかったです!

  5. 現在、包括的選言を表す方法はありますが、排他的多様性を表す方法はありません。我々はそれを表現するために排他的論理和の定義を使用することができる必要があります: ⊕  B  ≡( ∨  B)∧¬( ∧  B)。私は否定を書く方法を知らないが、私は¬ことを知っていますP  ≡  P  →⊥、と暗示と虚偽の両方が簡単です。したがって、私たちは以下によって排他的な選言を表すことができるはずです:

    data ⊥
    data Xor a b = Xor (Either a b) ((a,b) -> ⊥)
    

    これは、偽造に対応する、値のない空のタイプであると定義します。Xor次いで含むように定義されているの両方(およびAまたはBまたは)機能(含意から)(B) 及び下型(の))。 しかし、私はこれが何を意味するのか分かりません編集1:今、私はそうします、次の段落を参照してください!) タイプの値がない(あるのですか?)ので、プログラムでこれが何を意味するのか理解できません。この定義または別の定義のいずれかについて考えるより良い方法を誰かが知っていますか?Either(a,b) -> ⊥編集1:はい、camccann。)

    編集1:camccannの答え(特に、彼が私を助けるためにそれに残したコメント)おかげで、私はここで何が起こっているかを理解していると思います。typeの値を作成Xor a bするには、2つのことを提供する必要があります。最初に、aまたはb最初の引数として、またはいずれかの要素の存在を目撃します。つまり、Left aまたはRight bです。そして第二に、両方のタイプの要素がないことを証明aし、b言い換えれば、証明-in (a,b)無人の-とされる2番目の引数は。無人の(a,b) -> ⊥場合のみ関数を記述できるので、その場合(a,b)はどういう意味ですか?それはタイプのオブジェクトの一部が(a,b)構築できませんでした。言い換えれば、少なくとも一つの、そしておそらく両方のそれab同様無人のさ!この場合、パターンマッチングについて考えている場合、そのようなタプルでパターンマッチングを実行することはおそらくできません。それbが無人であると想定すると、そのタプルの2番目の部分に一致する可能性があるものを何と書きますか?したがって、それに対してパターンマッチを実行することはできません。これにより、これが無人になる理由を理解するのに役立ちます。ここで、引数を取らない完全な関数を使用する唯一の方法(これ(a,b)は無人なので、これは必須です)も結果を無人型にすることです。これをパターンマッチングの観点から考えると、これは、関数にケースがない場合でも、可能な本体がないことを意味します どちらでもかまいませんので、すべて問題ありません。

これの多くは私が声を出して/できれば(うまくいけば)その場で物事を証明することを考えていますが、それが役に立つことを願っています。私はウィキペディアの記事を本当にお勧めします。私はそれを詳細に読んだことはありませんが、その表は本当に素晴らしい要約であり、非常に徹底しています。


1
+1は、どちらかが包含的論理和であることを示します。(Either aa)は(all aの)定理であることに注意してください。
Apocalisp

質問再。2(b):居住者のみが非終了である関数型と無人関数型の違いは何ですか?たとえば、コンストラクターなしでタイプBを宣言し、関数A-> Bを次のように定義したとします。fun(a:A):B:= f(a)これは、それがBを返すことは不可能です。そのため、関数にはある意味で「居住」していますが、「居住者」はばかげています...そのため、実際にはまったく居住されていません。これが何らかの意味をなすことを願っています:)
Tom Crockett

3
ボトムは証明ではありません。「無知で不確定な要素を封じ込めて決定する必要があると考えるのは、ばかげたことで不可能です。」-アリストテレス
Apocalisp

2
@Tom:非終了に関する要点を理解するために、ロジックが一貫している場合、すべてのプログラムが終了します。非終了は、一貫性のないロジックを表す型システム、または同等にチューリング完全言語の型システムでのみ発生します。
CA McCann

1
Apocalisp: Either a a定理であってはならない:Either ⊥ ⊥まだ無人である。 Tom: camccannが言ったように、一貫性は終了を意味します。したがって、一貫した型システムではを表現できませんf :: a -> b。そのため、型は無人になります。一貫性のない型システム型の居住者を持っていますが、それは終了しません。 camccann:チューリング完全ではない一貫性のない型システムがあり、階層の中間点を占めていますか?または、その最後のステップ(一般的な再帰などを追加する)は、一貫性のない状態とまったく同じですか?
Antal Spector-Zabusky

12

ここで、以前に取り上げられなかったことに驚いたのは少し曖昧なものです。「古典的な」関数型反応プログラミングは時相論理に対応しています。

もちろん、あなたが哲学者、数学者、または強迫的な関数型プログラマでない限り、これはおそらくさらにいくつかの質問を引き起こします。

では、まず関数型リアクティブプログラミングとは何でしょうか。これは、時変値を処理する宣言的な方法です。ユーザーからの入力は時間とともに変化する値であるため、これはユーザーインターフェイスなどの記述に役立ちます。「クラシック」FRPには、イベントと動作という2つの基本的なデータタイプがあります。

イベントは、離散時間にのみ存在する値を表します。キーストロークは良い例です。キーボードからの入力を、ある時点での文字と考えることができます。キーを押すたびに、キーの文字とキーが押された時間のペアになります。

行動とは、常に存在する値ですが、継続的に変化する可能性があります。マウスの位置は良い例です。それは単にx、y座標の動作です。結局のところ、マウスには常に位置があり、概念的には、マウスを動かすと、この位置は絶えず変化します。結局のところ、マウスの移動は1回の長時間のアクションであり、個別のステップの束ではありません。

そして、時相論理とは何ですか?十分に適切なのは、時間とともに定量化された命題を処理するための一連の論理ルールです。基本的には、通常の1次論理を2つの量指定子□と◇で拡張します。1つ目は「常に」を意味します。「φは常に保持される」として□φを読み取ります。2つ目は「最終的に」:◇φは「最終的にφが成立する」という意味です。これは特別な種類のモーダルロジックです。次の2つの法則が数量詞に関連しています。

□φ ⇔ ¬◇¬φ
◇φ ⇔ ¬□¬φ

したがって、□と◇は∀とasと同じように互いに双対です。

これらの2つの量指定子は、FRPの2つのタイプに対応しています。特に、□は行動に対応し、◇はイベントに対応します。これらのタイプがどのように生息するかについて考える場合、これは理にかなっているはずです。行動は可能なすべての時間に生息し、イベントは1回だけ発生します。


8

継続と二重否定の間の関係に関連して、call / ccのタイプは、パースの法則ですhttp://en.wikipedia.org/wiki/Call-with-current-continuation

CHは通常、直観的なロジックとプログラムの間の対応として記述されます。ただし、call-with-current-continuation(callCC)演算子(タイプがPeirceの法則に対応する)を追加すると、古典的なロジックとcallCCを使用したプログラムとの対応が得られます。


4

これは単純な同型ではありませんが、建設的なLEMに関するこの議論は非常に興味深い結果です。特に、結論のセクションで、Oleg Kiselyovは、モナドを使用して構成論理で二重否定を排除することが、計算的に決定可能な命題(LEMが構成的設定で有効である)をすべての命題から区別することと類似していることについて説明します。モナドが計算効果を取り込むという概念は古いものですが、カリーのこのインスタンス-ハワード同型は、それを遠近法で捉え、二重否定が実際に「意味する」ことを理解するのに役立ちます。



4
2-continuation           | Sheffer stoke
n-continuation language  | Existential graph
Recursion                | Mathematical Induction

重要ですが、まだ調査されていない1つのことは、2-継続(2つのパラメーターをとる継続)とシェファーストロークの関係です。クラシックロジックでは、シェファーストロークはそれ自体で完全なロジックシステム(およびいくつかの非演算子の概念)を形成できます。つまり、おなじみのandornotシェファーのストークまたはを使用するだけで実装できますnand

これは、単一の型コンビネータを使用して他のすべての型を形成できることを促すので、プログラミング型の対応の重要な事実です。

2継続の型シグネチャは(a,b) -> Voidです。この実装により、1継続(通常の継続)を(a,a)-> Void、積タイプを((a,b)->Void,(a,b)->Void)->Void、合計タイプをとして定義できます((a,a)->Void,(b,b)->Void)->Void。これは、その表現力の印象を私たちに与えます。

さらに掘り下げると、Pieceの実存グラフは、データ型がn-継続のみの言語と同等であることがわかりますが、既存の言語がこの形式であるのはわかりませんでした。だから発明するのは面白いと思う。

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