简体   繁体   English

如何阅读GHC核心“证据”?

[英]How to read this GHC Core “proof”?

I wrote this small bit of Haskell to figure out how GHC proves that for natural numbers, you can only halve the even ones: 我写了一小部分Haskell来弄清楚GHC如何证明对于自然数,你只能将偶数的一半:

{-# 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)

The relevant parts of core become: 核心的相关部分变为:

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 }

I know the general flow of casting the types through instances of the Flip type family, but there are some things that I cannot completely follow: 我知道通过Flip类型系列的实例来转换类型的一般流程,但有些事情我无法完全遵循:

  • What's the meaning of @~ <Nat.Flip x_apH>_N ? @~ <Nat.Flip x_apH>_N是什么意思? is it the Flip instance for x? 它是x的Flip实例吗? How does that differ from @ (Nat.Flip x_apH) ? 这与@ (Nat.Flip x_apH)什么不同? I'm both interested in < > and _N 我对< >_N感兴趣

Regarding the first cast in halve : 对于一次投halve

  • What do dt_dK6 , dt1_dK7 and dt2_dK8 stand for? dt_dK6dt1_dK7dt2_dK8代表什么? I understand they are some kind of equivalence proofs, but which is which? 我知道它们是某种等价证明,但哪个是哪个?
  • I understand that Sym runs through an equivalence backwards 据我所知, Sym向后运行等价
  • What do the ; 做什么的; 's do? 的吗? Are the equivalence proofs just applied sequentially? 等效证明是否仅按顺序应用?
  • What are these _N and _R suffixes? 这些_N_R后缀是什么?
  • Are TFCo:R:Flip[0] and TFCo:R:Flip[1] the instances of Flip? TFCo:R:Flip[0]TFCo:R:Flip[1] Flip的实例?

@~ is coercion application. @~是胁迫申请。

The angle brackets denote a reflexive coercion of their contained type with role given by the underscored letter. 尖括号表示其所包含类型的反身强制与强调字母给出的作用。

Thus <Nat.Flip x_ap0H>_N is an equality proof that Nat.Flip x_apH is equal to Nat.Flip x_apH nominally (as equal types not just equal representations). 因此<Nat.Flip x_ap0H>_N是相等证明Nat.Flip x_apH等于Nat.Flip x_apH名义上(如等于类型不恰好等于表示)。

PS has a lot of arguments. PS有很多争论。 We look at the smart constructor $WPS and we can see the first two are the types of x and y respectively. 我们看一下智能构造函数$WPS ,我们可以看到前两个分别是x和y的类型。 We have proof that the constructor argument is Flip x (in this case we have Flip x ~ Even . We then have the proofs x ~ Flip y and y ~ Flip x . The final argument is a value of ParNat x . 我们已经证明构造函数参数是Flip x (在这种情况下我们有Flip x ~ Even 。然后我们有证明x ~ Flip yy ~ Flip x 。最后一个参数是ParNat x的值。

I will now walk through the first cast of type Nat.ParNat x_aIX ~# Nat.ParNat 'Nat.Odd 我现在将介绍Nat.ParNat x_aIX ~# Nat.ParNat 'Nat.Odd类型的第一个演员Nat.ParNat x_aIX ~# Nat.ParNat 'Nat.Odd

We start with (Nat.ParNat ...)_R . 我们从(Nat.ParNat ...)_R This is a type constructor application. 这是一个类型构造函数应用程序。 It lifts the proof of x_aIX ~# 'Nat.Odd to Nat.ParNat x_aIX ~# Nat.ParNat 'Nat.Odd . 它将x_aIX ~# 'Nat.Odd的证明x_aIX ~# 'Nat.OddNat.ParNat x_aIX ~# Nat.ParNat 'Nat.Odd The R means it does this representationally meaning that the types are isomorphic but not the same (in this case they are the same but we don't need that knowledge to perform the cast). R意味着它表示这意味着类型是同构的但不相同(在这种情况下它们是相同的但我们不需要那些知识来执行演员表)。

Now we look at main body of the proof (dt1_dK7 ; (Nat.Flip (dt2_dK8 ; Sym dt_dK6))_N; Nat.TFCo:R:Flip[0]) . 现在我们看一下证明的主体(dt1_dK7 ; (Nat.Flip (dt2_dK8 ; Sym dt_dK6))_N; Nat.TFCo:R:Flip[0]) ; means transitivty ie apply these proofs in order. 意味着过渡,即按顺序应用这些证明。

dt1_dK7 is a proof of x_aIX ~# Nat.Flip y_aIY . dt1_dK7x_aIX ~# Nat.Flip y_aIY的证明。

If we look at (dt2_dK8 ; Sym dt_dK6) . 如果我们看(dt2_dK8 ; Sym dt_dK6) dt2_dK8 shows y_aIY ~# Nat.Flip x_aIX . dt2_dK8显示y_aIY ~# Nat.Flip x_aIX dt_dK6 is of type 'Nat.Even ~# Nat.Flip x_aIX . dt_dK6的类型为'Nat.Even ~# Nat.Flip x_aIX So Sym dt_dK6 is of type Nat.Flip x_aIX ~# 'Nat.Even and (dt2_dK8 ; Sym dt_dK6) is of type y_aIY ~# 'Nat.Even 所以Sym dt_dK6属于Sym dt_dK6类型Nat.Flip x_aIX ~# 'Nat.Even(dt2_dK8 ; Sym dt_dK6)类型为y_aIY ~# 'Nat.Even

Thus (Nat.Flip (dt2_dK8 ; Sym dt_dK6))_N is a proof that Nat.Flip y_aIY ~# Nat.Flip 'Nat.Even . 因此(Nat.Flip (dt2_dK8 ; Sym dt_dK6))_NNat.Flip y_aIY ~# Nat.Flip 'Nat.Even

Nat.TFCo:R:Flip[0] is the first rule of flip which is Nat.Flip 'Nat.Even ~# 'Nat.Odd' . Nat.TFCo:R:Flip[0]是翻转的第一个规则,即Nat.Flip 'Nat.Even ~# 'Nat.Odd'

Putting these together we get (dt1_dK7 ; (Nat.Flip (dt2_dK8 ; Sym dt_dK6))_N; Nat.TFCo:R:Flip[0]) has type x_aIX #~ 'Nat.Odd . 将这些放在一起我们得到(dt1_dK7 ; (Nat.Flip (dt2_dK8 ; Sym dt_dK6))_N; Nat.TFCo:R:Flip[0])具有类型x_aIX #~ 'Nat.Odd

The second more complicated cast is a bit harder to work out but should work on the same principle. 第二个更复杂的演员阵容有点难以解决,但应该按照相同的原则工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM