Haskell 类型函数不能是内射的
我试图证明一些关于奇偶自然数的公理。我在证明中使用了三种定义的数据类型Haskell 类型函数不能是内射的,haskell,Haskell,我试图证明一些关于奇偶自然数的公理。我在证明中使用了三种定义的数据类型 data Nat = Z | S Nat data Even (a :: Nat) :: * where ZeroEven :: Even Z NextEven :: Even n -> Even (S (S n)) data Odd (a :: Nat) :: * where OneOdd :: Odd (S Z) NextOdd :: Odd n -> Odd (S (S n)) 我还为
data Nat = Z | S Nat
data Even (a :: Nat) :: * where
ZeroEven :: Even Z
NextEven :: Even n -> Even (S (S n))
data Odd (a :: Nat) :: * where
OneOdd :: Odd (S Z)
NextOdd :: Odd n -> Odd (S (S n))
我还为加法和乘法定义了以下类型族
type family Add (n :: Nat) (m :: Nat) :: Nat
type instance Add Z m = m
type instance Add (S n) m = S (Add n m)
type family Mult (n :: Nat) (m :: Nat) :: Nat
type instance Mult Z m = Z
type instance Mult (S n) m = Add (Mult n m) n
我定义了函数来证明两个偶数的和是偶数,两个偶数的乘积是偶数
evenPlusEven :: Even n -> Even m -> Even (Add n m)
evenPlusEven ZeroEven m = m
evenPlusEven (NextEven n) m = NextEven (evenPlusEven n m)
evenTimesEven :: Even n -> Even m -> Even (Mult n m)
evenTimesEven ZeroEven m = ZeroEven
evenTimesEven (NextEven n) m = evenPlusEven (EvenTimesEven n m) n
我使用的是GADTs
,datatypes
,TypeFamilies
,以及不可判定实例
语言扩展和GHC 7.10.3版。运行evenPlusEven
会得到我期望的结果,但是当我包含eventimesven
时,我会得到一个编译错误。错误是:
Could not deduce (Add (Add (Mult n1 m) n1) ('S n1)
~ Add (Mult n1 m) n1)
from the context (n ~ 'S ('S n1))
bound by a pattern with constructor
NextEven :: forall (n :: Nat). Even n -> Even ('S ('S n)),
in an equation for `evenTimesEven'
at OddsAndEvens.hs:71:16-25
NB: `Add' is a type function, and may not be injective
Expected type: Even (Mult n m)
Actual type: Even (Add (Mult n1 m) n1)
Relevant bindings include
m :: Even m
(bound at OddsAndEvens.hs:71:28)
n :: Even n1
(bound at OddsAndEvens.hs:71:25)
evenTimesEven :: Even n -> Even m -> Even (Mult n m)
(bound at OddsAndEvens.hs:70:1)
In the expression: evenPlusEven (evenTimesEven n m) n
In an equation for `evenTimesEven':
evenTimesEven (NextEven n) m = evenPlusEven (evenTimesEven n m) n
Mult
compile的类型族实例很好,如果我用错误抛出替换evenTimesEven
的最后一行,我可以编译代码,并且函数运行良好,输入ZeroEven
,这使我认为Mult
的实例是正确的,我的evenTimesEven
是问题所在,但我不确定原因
偶数(Mult n m)
和偶数(Add(Mult n1 m)n1)
不应该有相同的类型吗 下面,我将滥用常用的数学符号
from the context (n ~ 'S ('S n1))
由此,我们得到n=2+n1
Expected type: Even (Mult n m)
我们需要证明n*m
偶数,即(2+n1)*m
偶数
Actual type: Even (Add (Mult n1 m) n1)
我们已经证明了
(n1*m)+n1
是偶数。这是不一样的。附加的术语应该是m
,而不是n1
,并且应该添加两次。不应该evenPlusEven零偶m=n
beevenPlusEven零偶m=m
?为eventimesven
编写*
,evenPlusEven
编写+
,为nexteventimesven编写,你已经写了(2+n)*m=n*m+n
;它应该是(2+n)*m=n*m+m+m
或类似的格式。我无法编译evenPlusEven(evenTimesEven n m)(evenPlusEven m)
。这就是你想要的解决方案吗@4castle关联性很重要。这将使(n*m)+(m+m)
但是我想你需要((n*m)+m)+m)
。我心中没有解决方案,但如果在这样的练习中出现一些交换性或关联性问题,我不会感到惊讶。我发现一个打字错误,Add(Mult n m)n
应该是Add(Mult n m)m
,然后我应用了您的修复,现在它开始工作了!