-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdata_types_nat.hs
More file actions
60 lines (42 loc) · 1.72 KB
/
Copy pathdata_types_nat.hs
File metadata and controls
60 lines (42 loc) · 1.72 KB
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
data Nat = Zero | Suc Nat deriving (Show, Eq)
negative :: String -> a
negative f = error ("Data.Nat." ++ f ++ ": would be negative")
instance Enum Nat where
succ = Suc
pred = nat (negative "pred") id
instance Num Nat where
(+) n = foldNat n succ
(*) n = foldNat 0 (+n)
(-) n = nat n ((-) $! nat (negative "-") id n)
negate = nat 0 (const $ negative "negate")
abs = id
signum = nat 0 (const 1)
fromInteger = unfoldNat $ \n -> case n of n | n < 0 -> negative "fromInteger"
| n > 0 -> Just (n - 1)
| otherwise -> Nothing
toNatural = foldNat 0 succ
-- | Shallow deconstruction. Returns the first argument if @Zero@, applies the second argument to the inner value if @Succ@.
nat :: r -> (Nat -> r) -> Nat -> r
nat z s Zero = z
nat z s (Suc n) = s n
-- | Returns the first argument if @Zero@, applies the second argument recursively for each @Succ@.
foldNat :: r -> (r -> r) -> Nat -> r
foldNat z s = nat z (s . foldNat z s)
-- | Build a @Nat@ from a seed value: the first argument should return the next seed value
-- if the building is to continue, or @Nothing@ if it is to stop. A @Succ@ is added at each iteration.
unfoldNat :: (a -> Maybe a) -> a -> Nat
unfoldNat f a = maybe Zero (succ . unfoldNat f) (f a)
add :: Nat -> Nat -> Nat
add = (+)
mul :: Nat -> Nat -> Nat
mul = (*)
-- add :: Nat -> Nat -> Nat
-- add n = foldNat n Suc
-- mul :: Nat -> Nat -> Nat
-- mul n = foldNat 0 (+n)
fromNat :: Nat -> Integer
fromNat Zero = 0
fromNat (Suc n) = fromNat n + 1
fac :: Nat -> Nat
fac Zero = (Suc Zero)
fac n = n * (fac (pred n))