我不太确定这个ZInt究竟在描述什么。
data Nat = Zero | S Nat
data ZInt = Z Nat Nat deriving Show
addZ :: ZInt -> ZInt -> ZInt
addZ (Z a b) (Z c d) = Z (add a c) (add b d)
with
add :: Nat -> Nat -> Nat
add a Zero = a
add a (S b) = S (add a b)
mult :: Nat -> Nat -> Nat
mult _ Zero = Zero
mult a (S b) = add a (mult a b)
乍一看,我想也许这是一个复杂数字的表示,添加虚构和实际组件(在函数addZ中)而不显示
的形式a+b*i
但是这个功能发生了什么?
subZ :: ZInt -> ZInt -> ZInt
subZ (Z a b) (Z c d) = Z (add a d) (add b c)
multZ :: ZInt -> ZInt -> ZInt
multZ (Z a b) (Z c d) = Z (add (mult a d) (mult c b)) (add (mult a c) (mult b d))
所以我确实理解数据Nat = Zero | S nat以及add和mult函数,但不是addZ,subZ和multZ。
答案 0 :(得分:8)
它只是整数。 Nat
代表自然数。 ZInt
表示整数。在Z a b
if a >= b
中,则整数为a - b else - (b - a)。
例如:
ZInt representation | Traditional representation
Z Zero Zero | 0
Z (S Zero) Zero | 1
Z Zero (S Zero) | -1
Z (S Zero) (S Zero) | 0
...
我们可以看到,negate
一个整数,只需在其表示中交换Nat
值:
negate :: ZInt -> ZInt
negate (Z n m) = Z m n
我们可以像这样定义subZ
:
a `subZ` b = a `addZ` negate b
此表示不是规范的,Z (S Zero) (S Zero)
与Z Zero Zero
的整数相同。所以,我们可以像这样定义规范形式:
canonical :: ZInt -> ZInt
canonical (Z (S n) (S m)) = canonical (Z n m)
canonical x = x
通过这种方式定义整数的原因是什么?
首先,它在数学上是清晰的。如果有人定义了名为N
的自然数集,我们可以轻松地将名为Z
的整数集定义为Z = N * N
,其中(*)是两组的乘积。
在Haskell,我只能看到一个原因。通过这种方式,我们可以在类型级别上定义整数。
答案 1 :(得分:4)
首先,ZInt
将每个整数表示为有序自然数对。 @freestyle涵盖了这种表示如何运作良好;我将扩展算术运算符如何利用这种编码。
addZ
,subZ
和multZ
只是在操纵代表每个整数的一对自然数。
addZ (Z a b) (Z c d) = Z (add a c) (add b d)
(a - b) + (c - d) == a - b + c - d
== a + c - b - d
== (a + c) - (b + d)
subZ (Z a b) (Z c d) = Z (add a d) (add b c)
(a - b) - (c - d) == a - b - c + d
== a + d - b - c
== (a + d) - (b + c)
multZ (Z a b) (Z c d) = Z (add (mult a d) (mult c b)) (add (mult a c) (mult b d))
(a - b) * (c - d) == ac - ad - bc + bd
== ac + bd - ad - bc
== (ac + bd) - (ad + bc)
请注意,multZ
的给定定义可能会出现错误;它应该是
multZ (Z a b) (Z c d) = Z (add (mult a c) (mult b d)) (add (mult a d) (mult b c))
(为清楚起见,它也应该使用mult b c
而不是mult c b
,即使自然数的乘法是可交换的。)