Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xcode/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 基于本原递归的二元自然数加法_Haskell - Fatal编程技术网

Haskell 基于本原递归的二元自然数加法

Haskell 基于本原递归的二元自然数加法,haskell,Haskell,给定二进制自然数,零表示“两次”表示和“两次加一”表示。如何使用原语递归(仅使用函数foldBNat)表示加法 --zero | n*2 | n*2+1 数据BNat=Z | T BNat | TI BNat 派生(显示) foldBNat::BNat->t->(BNat->t->t)->(BNat->t->t)->t foldBNat n z t ti= 案例n Z->Z TM->TM(折叠NAT m z T ti) TI-m->TI-m(折叠式m-z-t-TI) div2::BNat->BN

给定二进制自然数,零表示“两次”表示和“两次加一”表示。如何使用原语递归(仅使用函数
foldBNat
)表示加法

--zero | n*2 | n*2+1
数据BNat=Z | T BNat | TI BNat
派生(显示)
foldBNat::BNat->t->(BNat->t->t)->(BNat->t->t)->t
foldBNat n z t ti=
案例n
Z->Z
TM->TM(折叠NAT m z T ti)
TI-m->TI-m(折叠式m-z-t-TI)
div2::BNat->BNat
div2 n=foldBNat n Z(\m\uuUm->m)(\m\uUm->m)
pred::BNat->BNat
pred n=foldBNat n Z(\\ur->TI r)(\m\ut->m)
成功::BNat->BNat
succn=foldbnatn(tiz)(\m\u->tim)(\\ur->tr)

想法:要计算
a+b
,我们需要增加
b
a
次。因此:

0 + b = b
1 + b = succ b
2 + b = succ (succ b)
3 + b = succ (succ (succ b))
...
incBy 0 = id
incBy 1 = succ
incBy 2 = succ . succ
incBy 3 = succ . succ . succ
...
我们可以从写作开始

plus a b = foldBNat a b (\m r -> ...
但是在这里我们被卡住了:
m
代表
a
的一半(因为这里
a=tm
,即
a=2*m
),而
r
b
m
次递增的结果(即
m+b
)。我们对此无能为力。我们想要的是
a+b=2*m+b
,这是我们无法直接从
m+b
获得的。应用
T
只会给我们
2*(m+b)=2*m+2*b
,这太大了,根据规则,我们不能直接递归
plus
来计算
m+(m+b)=2*m+b

我们需要的是一种更直接的方式来操作
succ
操作的数量

想法:不要直接计算一个数字;而是计算一个函数(将其参数递增一定次数)。因此:

我们可以直接实施:

incBy :: BNat -> (BNat -> BNat)
incBy n = foldBNat n id (\_ r -> r . r) (\_ r -> succ . r . r)
这里是
r。r
给我们提供了一个函数,该函数将一个数字的增量增加到
r
的两倍(通过应用
r
两次)

现在我们可以简单地将加法定义为:

plus :: BNat -> BNat -> BNat
plus n m = (incBy n) m

(这恰好是多余的,因为
plus=incBy
)。

谢谢,回答得很好!我希望有一种更有效的加法方法,但我想这里的问题是原始递归?结构递归会允许更有效的算法吗?一般递归呢?回答我自己的评论,使用结构/一般递归可以做得更好。