简体   繁体   中英

Addition for binary natural numbers using primitive recursion

Given binary natural numbers, with a zero case a "twice" case and a "twice plus one" case. How can one express addition using primitive recursion (using only the function 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)

Idea: To compute a + b , we need to increment b a times. So:

0 + b = b
1 + b = succ b
2 + b = succ (succ b)
3 + b = succ (succ (succ b))
...

We might start out by writing

plus a b = foldBNat a b (\m r -> ...

But here we get stuck: m represents half of a (since a = T m here, ie a = 2 * m ) and r is the result of incrementing b m times (ie m + b ). There's nothing useful we can do with that. What we want is a + b = 2*m + b , which we can't directly obtain from m + b . Applying T would only give us 2 * (m + b) = 2*m + 2*b , which is too big, and according to the rules we can't directly recurse on plus to compute m + (m + b) = 2*m + b .

What we need is a more direct way of manipulating the number of succ operations.

Idea: Don't compute a number directly; instead compute a function (that increments its argument a certain number of times). So:

incBy 0 = id
incBy 1 = succ
incBy 2 = succ . succ
incBy 3 = succ . succ . succ
...

We can implement that directly:

incBy :: BNat -> (BNat -> BNat)
incBy n = foldBNat n id (\_ r -> r . r) (\_ r -> succ . r . r)

Here r . r r . r gives us a function that increments a number twice as often as r does (by applying r twice).

Now we can simply define addition as:

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

(which happens to be redundant because plus = incBy ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM