このGHCコアの「証拠」を読む方法は?


84

私は、GHCが自然数の場合、偶数を半分にすることしかできないことをどのように証明するかを理解するために、このHaskellの小さなビットを書きました。

{-# LANGUAGE DataKinds, GADTs, KindSignatures, TypeFamilies #-}
module Nat where

data Nat = Z | S Nat

data Parity = Even | Odd

type family Flip (x :: Parity) :: Parity where
  Flip Even = Odd
  Flip Odd  = Even

data ParNat :: Parity -> * where
  PZ :: ParNat Even
  PS :: (x ~ Flip y, y ~ Flip x) => ParNat x -> ParNat (Flip x)

halve :: ParNat Even -> Nat
halve PZ     = Z
halve (PS a) = helper a
  where helper :: ParNat Odd -> Nat
        helper (PS b) = S (halve b)

コアの関連部分は次のようになります。

Nat.$WPZ :: Nat.ParNat 'Nat.Even
Nat.$WPZ = Nat.PZ @ 'Nat.Even @~ <'Nat.Even>_N

Nat.$WPS
  :: forall (x_apH :: Nat.Parity) (y_apI :: Nat.Parity).
     (x_apH ~ Nat.Flip y_apI, y_apI ~ Nat.Flip x_apH) =>
     Nat.ParNat x_apH -> Nat.ParNat (Nat.Flip x_apH)
Nat.$WPS =
  \ (@ (x_apH :: Nat.Parity))
    (@ (y_apI :: Nat.Parity))
    (dt_aqR :: x_apH ~ Nat.Flip y_apI)
    (dt_aqS :: y_apI ~ Nat.Flip x_apH)
    (dt_aqT :: Nat.ParNat x_apH) ->
    case dt_aqR of _ { GHC.Types.Eq# dt_aqU ->
    case dt_aqS of _ { GHC.Types.Eq# dt_aqV ->
    Nat.PS
      @ (Nat.Flip x_apH)
      @ x_apH
      @ y_apI
      @~ <Nat.Flip x_apH>_N
      @~ dt_aqU
      @~ dt_aqV
      dt_aqT
    }
    }

Rec {
Nat.halve :: Nat.ParNat 'Nat.Even -> Nat.Nat
Nat.halve =
  \ (ds_dJB :: Nat.ParNat 'Nat.Even) ->
    case ds_dJB of _ {
      Nat.PZ dt_dKD -> Nat.Z;
      Nat.PS @ x_aIX @ y_aIY dt_dK6 dt1_dK7 dt2_dK8 a_apK ->
        case a_apK
             `cast` ((Nat.ParNat
                        (dt1_dK7
                         ; (Nat.Flip (dt2_dK8 ; Sym dt_dK6))_N
                         ; Nat.TFCo:R:Flip[0]))_R
                     :: Nat.ParNat x_aIX ~# Nat.ParNat 'Nat.Odd)
        of _
        { Nat.PS @ x1_aJ4 @ y1_aJ5 dt3_dKa dt4_dKb dt5_dKc b_apM ->
        Nat.S
          (Nat.halve
             (b_apM
              `cast` ((Nat.ParNat
                         (dt4_dKb
                          ; (Nat.Flip
                               (dt5_dKc
                                ; Sym dt3_dKa
                                ; Sym Nat.TFCo:R:Flip[0]
                                ; (Nat.Flip (dt_dK6 ; Sym dt2_dK8))_N
                                ; Sym dt1_dK7))_N
                          ; Sym dt_dK6))_R
                      :: Nat.ParNat x1_aJ4 ~# Nat.ParNat 'Nat.Even)))
        }
    }
end Rec }

Flipタイプファミリーのインスタンスを介してタイプをキャストする一般的なフローは知っていますが、完全には理解できないことがいくつかあります。

  • の意味は@~ <Nat.Flip x_apH>_N何ですか?xのFlipインスタンスですか?それはどう違うの@ (Nat.Flip x_apH)ですか?私は両方に興味が< >あり、_N

の最初のキャストについてhalve

  • 何をdt_dK6dt1_dK7dt2_dK8のために立ちますか?それらはある種の同等性の証明であることを理解していますが、どれがどれですか?
  • 私はそれSymが逆に同等性を通過することを理解しています
  • は何をし;ますか?等価証明は順番に適用されますか?
  • これら_N_Rサフィックスは何ですか?
  • あるTFCo:R:Flip[0]TFCo:R:Flip[1]フリップのインスタンス?

6
私にはわかり
chi

訪問stackoverflow.com/questions/6121146/reading-ghc-core あなたのアイデアを得るの希望...
Hemant Ramphul

回答:


6

@~ 強制アプリケーションです。

山かっこは、下線付きの文字で示される役割を持つ、含まれているタイプの反射的な強制を示します。

従って<Nat.Flip x_ap0H>_N等価証拠であるNat.Flip x_apHと等しいNat.Flip x_apH(同じタイプだけでなく、同じ表現のような)名目上は。

PSには多くの議論があります。スマートコンストラクター$WPSを見ると、最初の2つはそれぞれxとyのタイプであることがわかります。コンストラクター引数がであるという証明がありますFlip x(この場合はFlip x ~ Even。があります。次に証明x ~ Flip yとがありy ~ Flip xます。最後の引数はの値ですParNat x

タイプの最初のキャストについて説明します Nat.ParNat x_aIX ~# Nat.ParNat 'Nat.Odd

から始め(Nat.ParNat ...)_Rます。これは型コンストラクターアプリケーションです。それは証明リフトx_aIX ~# 'Nat.OddにしますNat.ParNat x_aIX ~# Nat.ParNat 'Nat.Odd。これRは、型が同形であるが同じではないことを意味します(この場合、それらは同じですが、キャストを実行するためにその知識は必要ありません)。

次に、プルーフの本体を見てみましょう(dt1_dK7 ; (Nat.Flip (dt2_dK8 ; Sym dt_dK6))_N; Nat.TFCo:R:Flip[0]);一時性を意味します。つまり、これらの証明を順番に適用します。

dt1_dK7の証明ですx_aIX ~# Nat.Flip y_aIY

を見ると(dt2_dK8 ; Sym dt_dK6)dt2_dK8を示していますy_aIY ~# Nat.Flip x_aIXdt_dK6タイプ 'Nat.Even ~# Nat.Flip x_aIXです。つまりSym dt_dK6、タイプNat.Flip x_aIX ~# 'Nat.Even(dt2_dK8 ; Sym dt_dK6)あり、タイプですy_aIY ~# 'Nat.Even

したがって(Nat.Flip (dt2_dK8 ; Sym dt_dK6))_N、その証拠ですNat.Flip y_aIY ~# Nat.Flip 'Nat.Even

Nat.TFCo:R:Flip[0]フリップの最初のルールは Nat.Flip 'Nat.Even ~# 'Nat.Odd'です。

これらを組み合わせると、(dt1_dK7 ; (Nat.Flip (dt2_dK8 ; Sym dt_dK6))_N; Nat.TFCo:R:Flip[0])タイプが得られますx_aIX #~ 'Nat.Odd

2番目のより複雑なキャストは、解決するのが少し難しいですが、同じ原理で機能するはずです。


本当に私はその投稿をバウンスして、誰かがその混乱を理解できるかどうかを確認しました^^よくやったサー。
Jiri Trecak 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.