0 | module Algebra.Solver.Monoid
2 | import Syntax.PreorderReasoning
4 | import public Algebra.Group
5 | import public Algebra.Solver.Ops
6 | import public Data.List.Elem
21 | data Expr : (a : Type) -> (as : List a) -> Type where
24 | Lit : (lit : a) -> Expr a as
27 | Var : (x : a) -> Elem x as -> Expr a as
33 | (<+>) : Expr a as -> Expr a as -> Expr a as
38 | data Term : (a : Type) -> (as : List a) -> Type where
39 | TLit : (lit : a) -> Term a as
40 | TVar : (x : a) -> Elem x as -> Term a as
47 | public export %inline
48 | var : (x : a) -> {auto p : Elem x xs} -> Expr a xs
52 | public export %inline
53 | (.+>) : (x : a) -> Expr a xs -> {auto p : Elem x xs} -> Expr a xs
54 | (.+>) x y = Var x p <+> y
57 | public export %inline
58 | (<+.) : Expr a xs -> (x : a) -> {auto p : Elem x xs} -> Expr a xs
59 | (<+.) x y = x <+> Var y p
62 | public export %inline
65 | -> {auto p : Elem x xs}
66 | -> {auto q : Elem y xs}
68 | (.+.) x y = Var x p <+> Var y q
81 | -> {p : a -> a -> a}
82 | -> (0 m : Monoid a z p)
85 | eval m (Lit lit) = lit
86 | eval m (Var x _) = x
88 | eval m (x <+> y) = eval m x `p` eval m y
92 | eterm : Term a as -> a
93 | eterm (TLit lit) = lit
94 | eterm (TVar x y) = x
100 | -> {p : a -> a -> a}
101 | -> (0 m : Monoid a z p)
102 | -> List (Term a as)
105 | elist m (x :: xs) = eterm x `p` elist m xs
113 | flatten : Expr a as -> List (Term a as)
114 | flatten (Lit lit) = [TLit lit]
115 | flatten (Var x y) = [TVar x y]
116 | flatten Neutral = []
117 | flatten (x <+> y) = flatten x ++ flatten y
123 | -> {p : a -> a -> a}
124 | -> (0 m : Monoid a z p)
125 | -> (isZ : (v : a) -> Maybe (v === z))
126 | -> Term a as -> Term a as -> List (Term a as)
127 | fuse m isZ (TLit lit) (TLit x) = case isZ (lit `p` x) of
129 | Nothing => [TLit $
lit `p` x]
130 | fuse m isZ (TLit lit) t = case isZ lit of
132 | Nothing => [TLit lit, t]
133 | fuse m isZ x y = [x,y]
141 | -> {p : a -> a -> a}
142 | -> (0 m : Monoid a z p)
143 | -> (isZ : (v : a) -> Maybe (v === z))
144 | -> List (Term a as)
146 | -> List (Term a as)
147 | prepend m isZ [] (TVar x p) = [TVar x p]
148 | prepend m isZ [] (TLit x) = case isZ x of
150 | Nothing => [TLit x]
151 | prepend m isZ (x :: xs) t = fuse m isZ t x ++ xs
156 | -> {p : a -> a -> a}
157 | -> (0 m : Monoid a z p)
158 | -> (isZ : (v : a) -> Maybe (v === z))
159 | -> List (Term a as)
160 | -> List (Term a as)
161 | merge m isZ [] = []
162 | merge m isZ (x :: xs) = prepend m isZ (merge m isZ xs) x
167 | -> {p : a -> a -> a}
168 | -> (0 m : Monoid a z p)
169 | -> (isZ : (v : a) -> Maybe (v === z))
171 | -> List (Term a as)
172 | normalize m isZ e = merge m isZ (flatten e)
180 | -> (vs,ws : List (Term a as))
181 | -> elist m vs `p` elist m ws === elist m (vs ++ ws)
182 | pelist m [] ws = m.leftNeutral
183 | pelist m (v :: vs) ws = Calc $
184 | |~ (eterm v `p` elist m vs) `p` elist m ws
185 | ~~ eterm v `p` (elist m vs `p` elist m ws)
187 | ~~ eterm v `p` elist m (vs ++ ws)
188 | ... cong (eterm v `p`) (pelist m vs ws)
193 | -> eval m e === elist m (flatten e)
194 | pflatten m (Lit lit) = sym m.rightNeutral
195 | pflatten m (Var x y) = sym m.rightNeutral
196 | pflatten m Neutral = Refl
197 | pflatten m (x <+> y) = Calc $
198 | |~ eval m x `p` eval m y
199 | ~~ elist m (flatten x) `p` eval m y
200 | ... cong (`p` eval m y) (pflatten m x)
201 | ~~ elist m (flatten x) `p` elist m (flatten y)
202 | ... cong (elist m (flatten x) `p`) (pflatten m y)
203 | ~~ elist m (flatten x ++ flatten y)
204 | ... pelist m (flatten x) (flatten y)
208 | -> (isZ : (v : a) -> Maybe (v === z))
209 | -> (t1,t2 : Term a as)
210 | -> eterm t1 `p` eterm t2 === elist m (fuse m isZ t1 t2)
211 | pfuse m isZ (TLit lit) (TLit x) with (isZ $
lit `p` x)
212 | pfuse m isZ (TLit lit) (TLit x) | Just prf = prf
213 | pfuse m isZ (TLit lit) (TLit x) | Nothing = sym $
m.rightNeutral
215 | pfuse m isZ (TLit lit) (TVar x y) with (isZ lit)
216 | pfuse m isZ (TLit lit) (TVar x y) | Just prf = Calc $
218 | ~~ z `p` x ... cong (`p` x) prf
219 | ~~ x ... m.leftNeutral
220 | ~~ x `p` z ..< m.rightNeutral
221 | pfuse m isZ (TLit lit) (TVar x y) | Nothing =
222 | cong (lit `p`) $
sym m.rightNeutral
224 | pfuse m isZ (TVar x y) (TLit lit) = cong (x `p`) $
sym m.rightNeutral
225 | pfuse m isZ (TVar x y) (TVar w v) = cong (x `p`) $
sym m.rightNeutral
229 | -> (isZ : (v : a) -> Maybe (v === z))
230 | -> (ts : List (Term a as))
232 | -> eterm t `p` elist m ts === elist m (prepend m isZ ts t)
233 | pprepend m isZ [] (TVar x y) = Refl
234 | pprepend m isZ [] (TLit lit) with (isZ lit)
235 | pprepend m isZ [] (TLit lit) | Nothing = Refl
236 | pprepend m isZ [] (TLit lit) | Just prf = Calc $
238 | ~~ z `p` z ... cong (`p` z) prf
239 | ~~ z ... m.leftNeutral
240 | pprepend m isZ (x :: xs) t = Calc $
241 | |~ eterm t `p` (eterm x `p` elist m xs)
242 | ~~ (eterm t `p` eterm x) `p` elist m xs
244 | ~~ elist m (fuse m isZ t x) `p` elist m xs
245 | ... cong (`p` elist m xs) (pfuse m isZ t x)
246 | ~~ elist m (fuse m isZ t x ++ xs)
247 | ... pelist m (fuse m isZ t x) xs
251 | -> (isZ : (v : a) -> Maybe (v === z))
252 | -> (ts : List (Term a as))
253 | -> elist m ts === elist m (merge m isZ ts)
254 | pmerge m isZ [] = Refl
255 | pmerge m isZ (x :: xs) = Calc $
256 | |~ eterm x `p` elist m xs
257 | ~~ eterm x `p` elist m (merge m isZ xs)
258 | ... cong (eterm x `p`) (pmerge m isZ xs)
259 | ~~ elist m (prepend m isZ (merge m isZ xs) x)
260 | ... pprepend m isZ (merge m isZ xs) x
264 | -> (isZ : (x : a) -> Maybe (x === z))
266 | -> eval m e === elist m (normalize m isZ e)
267 | pnormalize m isZ e = Calc $
269 | ~~ elist m (flatten e) ... pflatten m e
270 | ~~ elist m (merge m isZ $
flatten e) ... pmerge m isZ (flatten e)
279 | -> (isZ : (x : a) -> Maybe (x === z))
280 | -> (e1,e2 : Expr a as)
281 | -> {auto prf : normalize m isZ e1 === normalize m isZ e2}
282 | -> eval m e1 === eval m e2
283 | solve m isZ e1 e2 = Calc $
285 | ~~ elist m (normalize m isZ e1) ... pnormalize m isZ e1
286 | ~~ elist m (normalize m isZ e2) ... cong (elist m) prf
287 | ~~ eval m e2 ..< pnormalize m isZ e2