Haskell 如何阅读本GHC核心文件“;证明;?
我写了这一小段Haskell来解释GHC如何证明自然数只能将偶数减半:Haskell 如何阅读本GHC核心文件“;证明;?,haskell,ghc,proof,haskell-platform,formal-verification,Haskell,Ghc,Proof,Haskell Platform,Formal Verification,我写了这一小段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
{-# 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 }
Nat.$WPZ::Nat.ParNat'Nat.偶
Nat.$WPZ=Nat.PZ@'Nat.偶@~Nat.Nat
纳特:减半=
\(d_dJB::Nat.ParNat'Nat.Even)->
个案D_dJB of{
Nat.PZ dt_dKD->Nat.Z;
Nat.PS@x_aIX@y_aIY dt_dK6 dt1_dK7 dt2_dK8 a_apK->
案例a_apK
`演员`((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)
的_
{Nat.PS@x1_aJ4@y1_aJ5 dt3_dKa dt4_dKb dt5_dKc b_apM->
纳特
(自然减半
(b_apM)
`演员`((Nat.ParNat)
(dt4_dKb)
(纳特·弗利普)
(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))\u R
::Nat.ParNat x1_aJ4~#Nat.ParNat'Nat.偶)
}
}
结束记录}
我知道通过翻转类型族的实例强制转换类型的一般流程,但有些事情我不能完全遵循:
的意思是什么?它是x的翻转实例吗?这与@~\N
有何不同?我对@(Nat.Flip x_apH)
和
都感兴趣\N
减半
:
、dt_dK6
和dt1_dK7
代表什么?我知道它们是某种等价证明,但哪一种是哪一种dt2_dK8
- 我知道
是通过一个等价关系运行的Sym
- 什么是
我们该怎么办?等价性证明是按顺序应用的吗
- 这些后缀是什么
和TFCo:R:Flip[0]
是Flip的实例吗TFCo:R:Flip[1]
@
是强制应用程序
尖括号表示其包含类型的反身强制,角色由带下划线的字母给出
因此,\N
是一个等式证明,Nat.Flip x_apH
名义上等于Nat.Flip x_apH
(作为相等的类型,而不仅仅是相等的表示)
PS有很多论点。我们查看智能构造函数$WPS
,我们可以看到前两个分别是x和y的类型。我们有证据证明构造函数参数是Flip x
(在这种情况下,我们有Flip x~偶数
。然后我们有证据x~ Flip y
和y~ Flip x
。最后一个参数是ParNat x
的值
现在,我将介绍类型Nat.ParNat x_aIX~#Nat.ParNat'Nat.Odd的第一次转换
我们从(Nat.ParNat…)(在这种情况下,它们是相同的,但我们不需要这些知识来执行演员阵容)
现在我们来看一下证明的主体(dt1\u dK7;(Nat.Flip(dt2\u dK8;Sym dt\u dK6))\N;Nat.TFCo:R:Flip[0])
,意味着传递,即按顺序应用这些证明
dt1_dK7
是x#u aIX~#Nat.Flip y_aIY
的证明
如果我们看一下(dt2_dK8;Sym dt_dK6)
dt2_dK8
显示y#aIY#Nat.Flip x#aIX
dt#dK6
属于类型的Nat.偶#Nat Nat
的类型为y#aIY##Nat.偶数
因此,(Nat.Flip(dt2_dK8;Sym dt_dK6))\N
证明了Nat.Flip y#aIY~#Nat.Flip'Nat.Even
Nat.TFCo:R:Flip[0]
是Flip的第一条规则,即Nat.Flip'Nat.偶~#'Nat.Odd'
把它们放在一起,我们得到了(dt1_dK7;(Nat.Flip(dt2_dK8;Sym dt_dK6))\N;Nat.TFCo:R:Flip[0])
的类型是x#aIX ~'Nat Odd
第二个更复杂的角色有点难演,但应该遵循同样的原则。我不知道,但我猜_N和_R是象征性和代表性的角色:访问希望你有想法。。真的,我刚刚发了那篇帖子,想看看是否有人能理解那团混乱。^干得好,先生。