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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
module Data.Nat (
Nat(..),
fromNat, toNat,
add, sub, mul,
leq
) where
import Test.Prop
data Nat = Z
| S Nat
deriving Eq
instance Show Nat where
show n = show (fromNat n)
instance Read Nat where
readsPrec p s = map (\ (n,r) -> (toNat n, r)) (readsPrec p s)
fromNat :: Nat -> Int
fromNat Z = 0
fromNat (S n) = 1 + fromNat n
fromNat'post :: Nat -> Int -> Bool
fromNat'post _ n = n >= 0
toNat :: Int -> Nat
toNat n | n == 0 = Z
| n > 0 = S (toNat (n - 1))
toNat'pre :: Int -> Bool
toNat'pre n = n >= 0
fromToNat :: Nat -> Prop
fromToNat n = toNat (fromNat n) -=- n
toFromNat :: Int -> Prop
toFromNat n = n>=0 ==> fromNat (toNat n) -=- n
add :: Nat -> Nat -> Nat
add Z n = n
add (S m) n = S (add m n)
addIsCommutative :: Nat -> Nat -> Prop
addIsCommutative x y = add x y -=- add y x
addIsAssociative :: Nat -> Nat -> Nat -> Prop
addIsAssociative x y z = add (add x y) z -=- add x (add y z)
sub :: Nat -> Nat -> Nat
sub x y | add y z == x = z where z free
subAddL :: Nat -> Nat -> Prop
subAddL x y = sub (add x y) x -=- y
subAddR :: Nat -> Nat -> Prop
subAddR x y = sub (add x y) y -=- x
mul :: Nat -> Nat -> Nat
mul Z _ = Z
mul (S m) n = add n (mul m n)
mulIsCommutative :: Nat -> Nat -> Prop
mulIsCommutative x y = mul x y -=- mul y x
mulIsAssociative :: Nat -> Nat -> Nat -> Prop
mulIsAssociative x y z = mul (mul x y) z -=- mul x (mul y z)
distMulAddL :: Nat -> Nat -> Nat -> Prop
distMulAddL x y z = mul x (add y z) -=- add (mul x y) (mul x z)
distMulAddR :: Nat -> Nat -> Nat -> Prop
distMulAddR x y z = mul (add y z) x -=- add (mul y x) (mul z x)
leq :: Nat -> Nat -> Bool
leq Z _ = True
leq (S _) Z = False
leq (S x) (S y) = leq x y
leqAdd :: Nat -> Nat -> Prop
leqAdd x y = always $ leq x (add x y)
instance Num Nat where
x + y = add x y
x - y = sub x y
x * y = mul x y
negate x = sub Z x
abs x = x
signum Z = Z
signum (S _) = S Z
fromInt x = toNat x
|