カレーハワードの述語論理への対応?


7

だから私は頭をカリーハワードに回そうとしている。(私は何度か試してみましたが、ゲル化していない/抽象的すぎるとは思われません)。具体的な問題に取り組むために、私はウィキペディアからリンクされたいくつかのHaskellチュートリアル、特にTim Newshamのチュートリアルに取り組んでいます。Newshamがチュートリアルを投稿したときにも役立つディスカッションがあります。

(しかし、私はNewshamとPiponiのdataラッパーを無視し、基礎となる型について話します。)ヒルベルトの公理スキーム(SKコンビネーターとして表されます)があります。タイプとしての命題があります。関数矢印としての意味; および関数アプリケーションとしてのModus Ponens:

axK :: p -> q -> p
axK  = const
axS :: (p -> q -> r) -> (p -> q) -> p -> r
axS     f                g          x  = f x (g x)

modPons = ($);   infixl 0 `modPons`          -- infix Left, cp ($) is Right

次に、アイデンティティ法を導出できます。

ident     = axS `modPons` axK `modPons` axK  -- (S K K)
-- ident :: p -> p                           -- inferred

これらの型を単に命題に対応する裸の型変数として持つことは、想像を絶するようです。より多くの型システムを使用して、命題を実際に構築できますか?考えている:

data      IsNat n  = IsNat !n                -- [Note **]

data      Z        = Z
axNatZ ::            IsNat Z
axNatZ             = IsNat Z

data      S n      = S !n
axNatS :: IsNat n -> IsNat (S n)
axNatS   (IsNat n) = IsNat (S n) 

twoIsNat = axNatS `modPons` (axNatS `modPons` axNatZ)
-- ===> IsNat (S (S Z))

[注意**] _ | _の導入を回避するために、ディスカッションスレッドに従って厳密なコンストラクターを使用しています。

どこ:

  • IsNat 述語です:用語から命題を作る。
  • n 変数です。
  • S 変数から項を作成する関数です。
  • Z 定数(ニラディック関数)です。

だから私は(一次)述語論理(?)を埋め込んだようです

私のタイプはあまり衛生的ではないことに感謝します。typevar-as-propositionとtypevar-as-termを簡単に組み合わせることができました。多分私はKindそれらを分離するためにシステムを使うべきです。OTOH私の公理は、どんな結論に至るにも見事に間違っているに違いありません。

私は表現していません:

  • 普遍的な量指定子:これは自由な変数に対して暗黙的です。
  • 存在量:実際には定数はスコーレム化された存在量として機能します。
  • 用語の同等性:含意の中で繰り返しtypevarを使用しました。
  • 関係:これはうまくいくようです、またはそれは困惑ですか?...
    data          PlusNat n m l  = PlusNat !n !m !l

    axPlusNatZ :: IsNat m       -> PlusNat Z m m
    axPlusNatZ   (IsNat m)       = PlusNat Z m m

    axPlusNatS :: PlusNat n m l -> PlusNat (S n) m (S l)
    axPlusNatS   (PlusNat n m l) = PlusNat (S n) m (S l)

    plus123 = axPlusNatS `modPons`
              (axPlusNatZ `modPons`
               (axNatS `modPons` (axNatS `modPons` axNatZ)) ) 
    -- ===> PlusNat (S Z) (S (S Z)) (S (S (S Z)))

公理の記述は簡単で、ワドラーの定理は無料です。。証明を書くのは大変です。(私はドロップしてmodPons関数アプリケーションを使用します。)

これは実際にロジックを実現していますか。それともクレイジーなものですか?脳に害を及ぼす前に止めるべきですか?

Curry-HowardでFOPLを表現するには、依存型が必要になるはずです。しかし、私はそうしていないようです(?)


1
あなたのアプローチの問題はIsNat、用語からの命題ではなく、命題からの命題です。
Derek Elkinsが

@DerekElkinsに感謝します。への引数IsNatは単なる型であるため、命題でなければなりません。OK、同じようIsNat nに単なるタイプなので、命題でなければなりません。n論理接続詞への引数として、提案領域/出現に逃げさせないように、「名誉」にならなければなりません(そのため、私はタイプの衛生について話しました)。NatsにChurchエンコーディングを使用した方が幸せですか?型レベルのコンストラクタでλ-calcを拡張しているだけだと思います。用語レベルのHaskellと同じです(?)
AntC

PSは、おそらくn ある命題:私が住んでいています"と言っています。これはCHの下でtypevarが言っていることと同じです。IsNat nが言っている/目撃している:さらに、の住民はn特定の「種類」、別名「ソート」の論理です。次に、単純に型指定されたλ-calc(?)を超えます
AntC、2017

1
難解なプログラミング言語をいじってカリーハワード同型を学ぶのは正しいアプローチだとは思いません。それは原則の真の理解につながることはありません。
Miles Rout 2017

1
テキストを理解していない場合は、テキストを理解するために必要なことを学ぶ必要があります。Haskellはそれらの1つではありません。
Miles Rout 2017

回答:


3

Newshamと(特に)Piponiのdataラッパーに不快である理由を説明するには...(これは答えよりも疑問ですが、おそらくNewsham IsNatに非常に似ているように見えても、私の問題の説明に役立つでしょう。 )

Piponiの17ページは次のとおりです。

data Proposition = Proposition :-> Proposition
                  | Symbol String
                  | False deriving Eq

data Proof = MP Proof Proof
     | Axiom String Proposition deriving Eq

ここにはタイプはありません。データコンストラクターのスペルは、:->機能を矢印にすることにはなりません。また、データコンストラクターMP(Modus Ponensの場合)をスペルしても、機能は適用されません。そこ「スマートコンストラクタ」演算子だ(@@)ためにはMP、それは何の関数を適用しません:それは単に上のパターンマッチングを行い:->、コンストラクタ。

ニューシャムは(私は含意セクション/モダスポネンスから始めます):

data Prop p = Prop p

data p :=> q = Imp (Prop p -> Prop q)

impInj :: (Prop p -> Prop q) -> Prop (p :=> q)
impInj p2q = Prop (Imp p2q)

impElim :: Prop p -> Prop (p :=> q) -> Prop q
impElim p (Prop (Imp p2q)) = p2q p

これはより似ています。タイプ、関数の矢印、関数のアプリケーションがありimpElimます。Imp注入と消去のルールを備えた型コンストラクターは、Curry-Howard同型の講義の証明ツリー構造を反映しています。しかし、私は緊張していImpます:なぜ型コンストラクタとデータコンストラクタが必要なのですか?繰り返しますが、スペル:=>は機能の矢印にはなりません。なぜこのすべてのラップおよびアンラップPropコンストラクターなのでしょうか。なぜ明白ではないのProp (p -> q)ですか?

だから私は(実際に最初に来る)「接続」セクションを見ると:

data p :/\ q = And (Prop p) (Prop q)

andInj :: Prop p -> Prop q -> Prop (p :/\ q)
andInj p q = Prop (And p q)

andElimL :: Prop (p :/\ q) -> Prop p
andElimL (Prop (And p q)) = p

andElimR :: Prop (p :/\ q) -> Prop q
andElimR (Prop (And p q)) = q

これらのElim関数関数アプリケーションを使用しません。それらは単にコンストラクターのパターンマッチです。結合に意味のある構造はありません。「プログラマ」がandInj規則を使用して型を構築しただけであることに完全に依存してい(p :/\ q)ます。

したがって、ニューシャムが結合詞の可換性に到達すると、次のようになります。

commuteAnd :: Prop (p :/\ q) -> Prop (q :/\ p)
commuteAnd pq = andInj (andElimR pq) (andElimL pq)

そして主張

Haskellの証明には(:/ \)データ型の内部構造への参照が含まれていないことに注意してください。「andInj」、「andElimR」、および「andElimL」のルールを定義して証明したので、(:/ \)データ型の実装を再度確認する必要はありません。

私は明白に同意しません:

  • のシグネチャは、型コンストラクタの内部構造に依存してcommuteAnd :/\ます。
  • 関数定義は単なる関数適用のように見えますが、実際にはandElims 構造を「覗き見」します。

私は、公理がそう言う必要なく、その定義から結合の可換性を証明できると期待します(?)

私がとても純粋であるなら、OK何を期待しますか?これは、ペアのチャーチエンコーディングに基づいています。

type Conj p q r = Prop ((p -> q -> r) -> r)     -- not right, see later

andInj :: Prop p -> Prop q -> Conj p q r
andInj (Prop p) (Prop q) = Prop (\elim -> elim p q)

andElimL :: Conj p q p -> Prop p
andElimL (Prop conj) = Prop (conj axK)    -- axK is `const`

これでcommuteAnd、「適切な」関数アプリケーションを使用して記述できます。

--  commuteAnd :: (Conj p q r) -> (Conj q p r)
commuteAnd pq = andInj (andElimR pq) (andElimL pq)

その関数の定義はNewshamのものと同じです。しかし、GHCの推定型は一般的ではないため、署名をコメント化しました。欲しいProp ((p -> p -> p) -> p) -> ((p -> p -> p) -> p)です。これは、アイデンティティ法の派手なバリエーションにすぎません。

編集:(@DerekElkinsの最初のコメントはここにあります。)これをすべてスクラップしてください:

結局、深い(そして濁った)水に浸かってしまいました。私のタイプはConjもっと多態的で、おそらくは命令的である必要があると思います。私はより高いランクのタイプを与えようとすることにうんざりしました:

type Conj p q = Prop (forall r.((p -> q -> r) -> r))

しかし、GHCはプレーしていません。(そして、Impredicativeポリモーフィズムのサポートは "不安定"です。)そして、forallそのような-数量化されたものは、私が使用することを期待していたFalse /無人の定義のように疑わしく見えます。

より高いランクのタイプが必要ですが、Impredicativeではありません。タイプではConjなく、commuteAnd

commuteAnd :: (forall r. Conj p q r) -> (Conj q p r')
-- (same function for `commuteAnd` as above)

OK。引数は無限に交換できます。

[編集の終わり]

だから私の質問:Newshamがどこでもコンストラクタとパターンマッチングをネストして何をしているのかが合法である場合、私IsNatとパターンマッチングについて合法ではないのは何ですか?


1
Piponiが述べているように、PropositionおよびProofタイプは、実際のカレーハワード通信の例ではありません。これらは単純なLCFスタイルの証明システムを形成するだけです。Curry-Howardの対応は、これらのsとsをHaskellコードに変換するcompile関数(ほとんどの作業は(^)and によって行われますshow)によって確認されます。Newshamのコードについては、ラッパーは本質的に違いを生じさせません。彼はそれらを(明示的に述べたように)追加するだけなので、後で別の重要な実装に入れ替えることができます。PropositionProof(:=>)(->)
Derek Elkinsが17/07/17にSE

ありがとう。ニーシャムについて、私はクラシックではなく直観主義の論理に固執したかった。だから継続/モナドのものは無視した。彼の防御力は直観主義には効かないと言っていますか?はい(:=>)はとして実装され(->)ます。ただし、ロジックのモデル/シミュレーションには、インタープリター(?)の検証が必要です。Haskellで直接表現できないのはなぜ(->)ですか?
AntC 2017

同様の発言はPiponiに関して:(^)クラシックを扱うために導入します。OK私は彼showにHaskellコードを生成させ、それがどのように違うのか見てみます。(私はまた彼がどのように導入しているかを理解しようとしますInteger。)私は最低限のHaskell機構を使用しようとしています_|_
AntC 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.