-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathInductive.hs
223 lines (168 loc) · 5.85 KB
/
Inductive.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
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
{-@ LIQUID "--reflection" @-}
{- LIQUID "--diff" @-}
{-@ LIQUID "--ple" @-}
{-@ infixr ++ @-} -- TODO: Silly to have to rewrite this annotation!
{-# LANGUAGE GADTs #-}
module Inductive where
import Prelude hiding ((++))
import ProofCombinators
import Lists
import Expressions
import qualified State as S
--------------------------------------------------------------------------------
-- | Peano numbers
--------------------------------------------------------------------------------
data Peano = Z | S Peano
--------------------------------------------------------------------------------
-- | Defining "Even Numbers"
--------------------------------------------------------------------------------
-- | The "Prop" describing an Even number `(Ev n)`
data EvP where
Ev :: Peano -> EvP
-- | The ways to "construct evidence" of evenness i.e. that "prove" `Ev n`
data Ev where
EvZ :: Ev
EvS :: Peano -> Ev -> Ev
{-@ data Ev where
EvZ :: Prop (Ev Z)
| EvS :: n:Peano -> Prop (Ev n) -> Prop (Ev (S (S n)))
@-}
{- | Read the above as there are two "rules" to determine even-ness
1.
------------------ [EvZ]
Ev Z
2.
Ev n
------------------ [EvS]
Ev (S (S n))
-}
{-@ measure evNat @-}
{-@ evNat :: Ev -> Nat @-}
evNat :: Ev -> Int
evNat EvZ = 0
evNat (EvS _ p) = 1 + evNat p
--------------------------------------------------------------------------------
{-@ reflect evn @-}
evn :: Peano -> Bool
evn Z = True
evn (S Z) = False
evn (S (S n)) = evn n
{-@ ple lemma_ev @-}
{-@ lemma_ev :: n:_ -> Prop (Ev n) -> {evn n} @-}
lemma_ev :: Peano -> Ev -> Proof
lemma_ev Z _ = ()
lemma_ev (S Z) EvZ = ()
lemma_ev (S Z) (EvS _ _) = ()
lemma_ev (S (S n)) (EvS _ pn) = lemma_ev n pn
{-@ ple lemma_evn @-}
{-@ lemma_evn :: n:{_ | evn n} -> Prop (Ev n) @-}
lemma_evn :: Peano -> Ev
lemma_evn Z = EvZ
lemma_evn (S (S n)) = EvS n (lemma_evn n)
--------------------------------------------------------------------------------
-- | Section 4.5.2 IndStar
--------------------------------------------------------------------------------
-- Relations
type Rel a = a -> a -> Bool
-- | The Prop describing the closure of a relation
data StarP a where
Star :: Rel a -> a -> a -> StarP a
-- | The Predicate describing the closure of a relation
data Star a where
Refl :: Rel a -> a -> Star a
Step :: Rel a -> a -> a -> a -> Star a -> Star a
{-@ data Star a where
Refl :: r:Rel a -> x:a -> Prop (Star r x x)
| Step :: r:Rel a -> x:a -> y:{a | r x y} -> z:a -> Prop (Star r y z)
-> Prop (Star r x z)
@-}
{-@ measure starNat @-}
{-@ starNat :: Star a -> Nat @-}
starNat :: Star a -> Int
starNat (Refl _ _) = 0
starNat (Step _ _ _ _ s) = 1 + starNat s
--------------------------------------------------------------------------------
{-@ lemma_star_trans :: r:Rel a -> x:a -> y:a -> z:a
-> Prop (Star r x y)
-> Prop (Star r y z)
-> Prop (Star r x z)
@-}
lemma_star_trans :: Rel a -> a -> a -> a -> Star a -> Star a -> Star a
lemma_star_trans r x y z (Refl _ _) yz = yz
lemma_star_trans r x y z (Step _ _ x1 _ x1y) yz = Step r x x1 z (lemma_star_trans r x1 y z x1y yz)
--------------------------------------------------------------------------------
-- | The Prop declaring the Palindrome predicate
data PalP a where
Pal :: [a] -> PalP a
-- | The Predicate implementing the Palindrom predicate
data Pal a where
Pal0 :: Pal a
Pal1 :: a -> Pal a
Pals :: a -> [a] -> Pal a -> Pal a
{-@ data Pal a where
Pal0 :: Prop (Pal [])
| Pal1 :: x:_ -> Prop (Pal (single x))
| Pals :: x:_ -> xs:_ -> Prop (Pal xs) -> Prop (Pal (mkPal x xs))
@-}
{-@ reflect single @-}
single :: a -> [a]
single x = [x]
{-@ reflect mkPal @-}
mkPal :: a -> [a] -> [a]
mkPal x xs = x : (xs ++ [x])
{-@ measure palNat @-}
{-@ palNat :: Pal a -> Nat @-}
palNat :: Pal a -> Int
palNat (Pal0 {}) = 0
palNat (Pal1 {}) = 0
palNat (Pals _ _ p) = 1 + palNat p
{-@ ple lemma_pal @-}
{-@ lemma_pal :: xs:_ -> p:Prop (Pal xs) -> { xs = rev xs } / [palNat p] @-}
lemma_pal :: [a] -> Pal a -> Proof
lemma_pal [] (Pal0) = ()
lemma_pal [_] (Pal1 _) = ()
lemma_pal xs (Pals y ys pys) =
-- rev xs
-- === rev (mkPal y ys)
-- === rev (y : (ys ++ [y]))
-- ===
(rev (ys ++ [y])) ++ [y] --
? lemma_rev_app ys [y]
-- === ([y] ++ rev ys) ++ [y]
? lemma_pal ys pys
-- === xs
*** QED
--------------------------------------------------------------------------------
-- | The Prop declaring the AvRel predicate
data AvRelP where
AvRel :: State -> AExp -> Val -> AvRelP
-- | The Predicate implementing the Palindrom predicate
data AvRel where
AvRelN :: State -> Val -> AvRel
AvRelV :: State -> Vname -> AvRel
AvRelP :: State -> AExp -> Val -> AExp -> Val -> AvRel -> AvRel -> AvRel
{-@ data AvRel where
AvRelN :: s:_ -> n:_
-> Prop (AvRel s (N n) n)
| AvRelV :: s:_ -> x:_
-> Prop (AvRel s (V x) (S.get s x))
| AvRelP :: s:_ -> a1:_ -> v1:_ -> a2:_ -> v2:_
-> Prop (AvRel s a1 v1)
-> Prop (AvRel s a2 v2)
-> Prop (AvRel s (Plus a1 a2) (add v1 v2))
@-}
{-@ lem_avrel :: s:_ -> a:_ -> n:_ -> Prop (AvRel s a n)
-> { n == aval a s } @-}
lem_avrel :: State -> AExp -> Val -> AvRel -> Proof
lem_avrel s (N n) _n (AvRelN {})
= ()
lem_avrel s (V x) _ (AvRelV {})
= ()
lem_avrel s (Plus a1 a2) _ (AvRelP _s _a1 n1 _a2 n2 p_a1_n1 p_a2_n2)
= lem_avrel s a1 n1 p_a1_n1 -- aval a1 s == n1
&&& lem_avrel s a2 n2 p_a2_n2 -- aval a2 s == n2
lem_avrel s _ _ _ = impossible ""
-- s:_ -> a:_ -> n:{ n = aval a s } -> Prop (AvRel s a n)
{-@ reflect add @-}
add :: Val -> Val -> Val
add x y = x + y