![](/img/trans.png)
[英]Using the addition function over the natural numbers, give a recursive definition of multiplication of natural numbers?
[英]Addition for binary natural numbers using primitive recursion
給定二進制自然數,零情況下為“兩次”情況,“兩次加一”情況。 如何使用原始遞歸表示添加(僅使用函數foldBNat
)?
-- zero | n * 2 | n * 2 + 1
data BNat = Z | T BNat | TI BNat
deriving (Show)
foldBNat :: BNat -> t -> (BNat -> t -> t) -> (BNat -> t -> t) -> t
foldBNat n z t ti =
case n of
Z -> z
T m -> t m (foldBNat m z t ti)
TI m -> ti m (foldBNat m z t ti)
div2 :: BNat -> BNat
div2 n = foldBNat n Z (\m _ -> m) (\m _ -> m)
pred :: BNat -> BNat
pred n = foldBNat n Z (\_ r -> TI r) (\m _ -> T m)
succ :: BNat -> BNat
succ n = foldBNat n (TI Z) (\m _ -> TI m) (\_ r -> T r)
點子:要計算a + b
,我們需要增加b
a
時代。 所以:
0 + b = b
1 + b = succ b
2 + b = succ (succ b)
3 + b = succ (succ (succ b))
...
我們可以從寫作開始
plus a b = foldBNat a b (\m r -> ...
但在這里我們遇到問題: m
代表的半數a
(因為a = T m
在這里,即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 0 = id
incBy 1 = succ
incBy 2 = succ . succ
incBy 3 = succ . succ . succ
...
我們可以直接實現:
incBy :: BNat -> (BNat -> BNat)
incBy n = foldBNat n id (\_ r -> r . r) (\_ r -> succ . r . r)
這里是r . r
r . r
給了我們兩次盡可能多增加一些功能r
做(通過應用r
兩次)。
現在我們可以簡單地將添加定義為:
plus :: BNat -> BNat -> BNat
plus n m = (incBy n) m
(這恰好是多余的,因為plus = incBy
)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.