-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNatRaw.hs
71 lines (56 loc) · 1.31 KB
/
NatRaw.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module NatRaw
(
Nat
, uu, vv, phi, psi
) where
newtype Nat = Nat { getNat :: Integer }
deriving (Eq, Ord, Real, Enum, Integral)
instance Show Nat where
showsPrec d (Nat n) = showsPrec d n
instance Num Nat where
fromInteger n
| n >= 0 = Nat n
| otherwise = error "fromInteger Nat: negative"
(Nat n) + (Nat m) = Nat (n + m)
(Nat n) * (Nat m) = Nat (n * m)
abs = id
signum (Nat 0) = (Nat 0)
signum (Nat _) = (Nat 1)
(Nat n) - (Nat m) = let k = n - m in if k >= 0
then Nat k
else error "(-) Nat: negative"
uu :: (Nat, Nat) -> Nat
uu (0, 0) = 0
uu (n, m) = let
(n', rn) = n `divMod` 2
(m', rm) = m `divMod` 2
in rn + 2 * (rm + 2 * uu (n', m'))
vv :: Nat -> (Nat, Nat)
vv 0 = (0, 0)
vv k = let
(l, rn) = k `divMod` 2
(k', rm) = l `divMod` 2
(n', m') = vv k'
in (rn + 2 * n', rm + 2 * m')
{- this encoding is slow !!
uu :: (Nat, Nat) -> Nat
uu (l, r) =
if r == 0
then phi (Left l)
else phi (Right $ uu (l, r - 1))
vv :: Nat -> (Nat, Nat)
vv n =
case psi n of
Left m -> (m, 0)
Right m -> let (l, r) = vv m in (l, r + 1)
-}
phi :: Either Nat Nat -> Nat
phi (Left n) = 2 * n
phi (Right n) = 2 * n + 1
psi :: Nat -> Either Nat Nat
psi n = let
(q,r) = n `divMod` 2
in if r == 0
then Left q
else Right q