簡體   English   中英

使用原始遞歸添加二進制自然數

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM