0 | module Algebra.Solver.Semigroup
2 | import Syntax.PreorderReasoning
4 | import public Algebra.Group
5 | import public Algebra.Solver.Ops
6 | import public Data.List1
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
30 | (<+>) : Expr a as -> Expr a as -> Expr a as
35 | data Term : (a : Type) -> (as : List a) -> Type where
36 | TLit : (lit : a) -> Term a as
37 | TVar : (x : a) -> Elem x as -> Term a as
44 | public export %inline
45 | var : (x : a) -> {auto p : Elem x xs} -> Expr a xs
49 | public export %inline
50 | (.+>) : (x : a) -> Expr a xs -> {auto p : Elem x xs} -> Expr a xs
51 | (.+>) x y = Var x p <+> y
54 | public export %inline
55 | (<+.) : Expr a xs -> (x : a) -> {auto p : Elem x xs} -> Expr a xs
56 | (<+.) x y = x <+> Var y p
59 | public export %inline
62 | -> {auto p : Elem x xs}
63 | -> {auto q : Elem y xs}
65 | (.+.) x y = Var x p <+> Var y q
76 | eval : {p : a -> a -> a} -> (0 s : Semigroup a p) -> Expr a as -> a
77 | eval s (Lit lit) = lit
78 | eval s (Var x _) = x
79 | eval s (x <+> y) = eval s x `p` eval s y
83 | eterm : Term a as -> a
84 | eterm (TLit lit) = lit
85 | eterm (TVar x y) = x
91 | -> (0 s : Semigroup a p)
95 | elist s v [] = eterm v
96 | elist s v (x :: xs) = eterm v `p` elist s x xs
100 | elist1 : {p : a -> a -> a} -> (0 s : Semigroup a p) -> List1 (Term a as) -> a
101 | elist1 s (h ::: t) = elist s h t
109 | flatten : Expr a as -> List1 (Term a as)
110 | flatten (Lit lit) = TLit lit ::: []
111 | flatten (Var x y) = TVar x y ::: []
112 | flatten (x <+> y) = flatten x ++ flatten y
120 | -> (0 s : Semigroup a p)
121 | -> List1 (Term a as)
123 | -> List1 (Term a as)
124 | prepend s (TLit x ::: xs) (TLit y) = TLit (y `p` x) ::: xs
125 | prepend s (x ::: xs) y = y ::: x :: xs
130 | -> (0 s : Semigroup a p)
132 | -> List (Term a as)
133 | -> List1 (Term a as)
134 | merge s t [] = t ::: []
135 | merge s t (x :: xs) = prepend s (merge s x xs) t
140 | -> (0 s : Semigroup a p)
141 | -> List1 (Term a as)
142 | -> List1 (Term a as)
143 | merge1 s (t ::: ts) = merge s t ts
146 | normalize : {p : _} -> (0 s : Semigroup a p) -> Expr a as -> List1 (Term a as)
147 | normalize s e = merge1 s (flatten e)
154 | (s : Semigroup a p)
157 | -> (vs : List (Term a as))
158 | -> (ws : List (Term a as))
159 | -> elist s v vs `p` elist s w ws === elist s v (vs ++ w :: ws)
160 | pelist s v w [] ws = Refl
161 | pelist s v w (x :: xs) ws = Calc $
162 | |~ (eterm v `p` elist s x xs) `p` elist s w ws
163 | ~~ eterm v `p` (elist s x xs `p` elist s w ws)
165 | ~~ eterm v `p` elist s x (xs ++ (w :: ws))
166 | ... cong (eterm v `p`) (pelist s x w xs ws)
169 | (s : Semigroup a p)
170 | -> (vs : List1 (Term a as))
171 | -> (ws : List1 (Term a as))
172 | -> elist1 s vs `p` elist1 s ws === elist1 s (vs ++ ws)
173 | pelist1 s (v ::: vs) (w ::: ws) = pelist s v w vs ws
176 | (s : Semigroup a p)
178 | -> eval s e === elist1 s (flatten e)
179 | pflatten s (Lit lit) = Refl
180 | pflatten s (Var x y) = Refl
181 | pflatten s (x <+> y) = Calc $
182 | |~ eval s x `p` eval s y
183 | ~~ elist1 s (flatten x) `p` eval s y
184 | ... cong (`p` eval s y) (pflatten s x)
185 | ~~ elist1 s (flatten x) `p` elist1 s (flatten y)
186 | ... cong (elist1 s (flatten x) `p`) (pflatten s y)
187 | ~~ elist1 s (flatten x ++ flatten y)
188 | ... pelist1 s (flatten x) (flatten y)
191 | (s : Semigroup a p)
192 | -> (ts : List1 (Term a as))
194 | -> eterm t `p` elist1 s ts === elist1 s (prepend s ts t)
195 | pprepend s (TLit lit ::: []) (TLit x) = Refl
196 | pprepend s (TLit lit ::: t :: ts) (TLit x) = s.associative
197 | pprepend s (TLit lit ::: ts) (TVar x y) = Refl
198 | pprepend s (TVar x y ::: ts) (TLit lit) = Refl
199 | pprepend s (TVar x y ::: ts) (TVar z w) = Refl
202 | (s : Semigroup a p)
204 | -> (ts : List (Term a as))
205 | -> elist s t ts === elist1 s (merge s t ts)
206 | pmerge s t [] = Refl
207 | pmerge s t (x :: xs) = Calc $
208 | |~ eterm t `p` elist s x xs
209 | ~~ eterm t `p` elist1 s (merge s x xs)
210 | ... cong (eterm t `p`) (pmerge s x xs)
211 | ~~ elist1 s (prepend s (merge s x xs) t)
212 | ... pprepend s (merge s x xs) t
215 | (s : Semigroup a p)
216 | -> (ts : List1 (Term a as))
217 | -> elist1 s ts === elist1 s (merge1 s ts)
218 | pmerge1 s (t ::: ts) = pmerge s t ts
221 | (s : Semigroup a p)
223 | -> eval s e === elist1 s (normalize s e)
224 | pnormalize s e = Calc $
226 | ~~ elist1 s (flatten e) ... pflatten s e
227 | ~~ elist1 s (merge1 s $
flatten e) ... pmerge1 s (flatten e)
235 | (s : Semigroup a p)
236 | -> (e1,e2 : Expr a as)
237 | -> {auto prf : normalize s e1 === normalize s e2}
238 | -> eval s e1 === eval s e2
239 | solve s e1 e2 = Calc $
241 | ~~ elist1 s (normalize s e1) ... pnormalize s e1
242 | ~~ elist1 s (normalize s e2) ... cong (elist1 s) prf
243 | ~~ eval s e2 ..< pnormalize s e2