diff options
Diffstat (limited to 'src/Data/Term/Unify.idr')
-rw-r--r-- | src/Data/Term/Unify.idr | 603 |
1 files changed, 273 insertions, 330 deletions
diff --git a/src/Data/Term/Unify.idr b/src/Data/Term/Unify.idr index b87ab21..b4f7ebd 100644 --- a/src/Data/Term/Unify.idr +++ b/src/Data/Term/Unify.idr @@ -1,10 +1,6 @@ module Data.Term.Unify -import Data.DPair import Data.Fin.Occurs -import Data.Fin.Strong -import Data.Maybe.Properties -import Data.Singleton import Data.Term import Data.Term.Property import Data.Term.Zipper @@ -16,10 +12,10 @@ import Syntax.PreorderReasoning -- Check ----------------------------------------------------------------------- export -check : SFin k -> Term sig k -> Maybe (Term sig (pred k)) -checkAll : SFin k -> Vect n (Term sig k) -> Maybe (Vect n (Term sig (pred k))) +check : {k : Nat} -> Fin (S k) -> Term sig (S k) -> Maybe (Term sig k) +checkAll : {k : Nat} -> Fin (S k) -> Vect n (Term sig (S k)) -> Maybe (Vect n (Term sig k)) -check x (Var y) = Var' <$> thick x y +check x (Var y) = Var <$> thick x y check x (Op op ts) = Op op <$> checkAll x ts checkAll x [] = Just [] @@ -27,168 +23,97 @@ checkAll x (t :: ts) = [| check x t :: checkAll x ts |] -- Properties -export -checkOccurs : - (x : SFin k) -> - (zip : Zipper sig k) -> - IsNothing (check x (zip + Var' x)) -checkAllOccurs : - (x : SFin k) -> - (i : SFin n) -> - (ts : Vect (pred n) (Term sig k)) -> - (zip : Zipper sig k) -> - IsNothing (checkAll x (insertAt' i (zip + Var' x) ts)) - -checkOccurs x Top = mapNothing Var' (thickRefl x) -checkOccurs x (Op op i ts zip) = mapNothing (Op op) (checkAllOccurs x i ts zip) - -checkAllOccurs x FZ ts zip = - appLeftNothingIsNothing - (appRightNothingIsNothing (Just (::)) (checkOccurs x zip)) - (checkAll x ts) -checkAllOccurs x (FS i) (t :: ts) zip = - appRightNothingIsNothing - (Just (::) <*> check x t) - (checkAllOccurs x i ts zip) - -export -checkNothing : - (x : SFin k) -> - (t : Term sig k) -> - (0 _ : IsNothing (check x t)) -> - (zip : Zipper sig k ** t = zip + Var' x) -checkAllNothing : - (x : SFin k) -> - (t : Term sig k) -> - (ts : Vect n (Term sig k)) -> - (0 _ : IsNothing (checkAll x (t :: ts))) -> - (i ** ts' ** zip : Zipper sig k ** t :: ts = insertAt' i (zip + Var' x) ts') - -checkNothing x (Var y) prf = - (Top ** sym (cong Var (thickNothing x y (mapNothingInverse Var' (thick x y) prf)))) -checkNothing x (Op op (t :: ts)) prf = - let (i ** ts' ** zip ** prf) = checkAllNothing x t ts (mapNothingInverse (Op op) _ prf) in - (Op op i ts' zip ** cong (Op op) prf) - -checkAllNothing x t ts prf with (appNothingInverse (Just (::) <*> check x t) (checkAll x ts) prf) - _ | Left prf' = case appNothingInverse (Just (::)) (check x t) prf' of - Right prf => - let (zip ** prf) = checkNothing x t prf in - (FZ ** ts ** zip ** cong (:: ts) prf) - checkAllNothing x t (t' :: ts) prf | Right prf' = - let (i ** ts ** zip ** prf) = checkAllNothing x t' ts prf' in - (FS i ** t :: ts ** zip ** cong (t ::) prf) - -export -checkThin : - (x : SFin (S k)) -> - (t : Term sig k) -> - IsJust (check x (pure (thin x) <$> t)) -checkAllThin : - (x : SFin (S k)) -> - (ts : Vect n (Term sig k)) -> - IsJust (checkAll x (map (pure (thin x) <$>) ts)) - -checkThin x (Var y) = - mapIsJust Var' $ - thickNeq x (thin x y) (\prf => thinSkips x y $ sym prf) -checkThin x (Op op ts) = mapIsJust (Op op) (checkAllThin x ts) - -checkAllThin x [] = ItIsJust -checkAllThin x (t :: ts) = - appIsJust - (appIsJust ItIsJust (checkThin x t)) - (checkAllThin x ts) +public export +data CheckProof : Fin (S k) -> Term sig (S k) -> Maybe (Term sig k) -> Type where + Occurs : (zip : Zipper sig (S k)) -> res = Nothing -> CheckProof x (zip + Var x) res + Stronger : (t : Term sig k) -> res = Just t -> CheckProof x (pure (thin x) <$> t) res + +data CheckAllProof : Fin (S k) -> Vect n (Term sig (S k)) -> Maybe (Vect n (Term sig k)) -> Type where + OccursAt : + (i : Fin (S n)) -> + (ts : Vect n (Term sig (S k))) -> + (zip : Zipper sig (S k)) -> + res = Nothing -> + CheckAllProof x (insertAt i (zip + Var x) ts) res + AllStronger : + (ts : Vect n (Term sig k)) -> + res = Just ts -> + CheckAllProof x (map (pure (thin x) <$>) ts) res export -checkJust : - (x : SFin k) -> - (t : Term sig k) -> - (0 _ : check x t = Just u) -> - t = pure (thin x) <$> u -checkAllJust : - (x : SFin k) -> - (ts : Vect n (Term sig k)) -> - (0 _ : checkAll x ts = Just us) -> - ts = map (pure (thin x) <$>) us - -checkJust x (Var y) prf = - let 0 z = mapJustInverse Var' (thick x y) prf in - let 0 prf = thickJust x y (fst z.snd) in - sym $ Calc $ - |~ pure (thin x) <$> u - ~~ pure (thin x) <$> Var' z.fst ...(cong (pure (thin x) <$>) $ snd z.snd) - ~~ Var' y ...(cong Var' prf) -checkJust x (Op op ts) prf = - let 0 z = mapJustInverse (Op op) (checkAll x ts) prf in - let 0 prf = checkAllJust x ts (fst z.snd) in - Calc $ - |~ Op op ts - ~~ pure (thin x) <$> Op op z.fst ...(cong (Op op) prf) - ~~ pure (thin x) <$> u ...(sym $ cong (pure (thin x) <$>) $ snd z.snd) - -checkAllJust x [] Refl = Refl -checkAllJust x (t :: ts) prf = - let 0 z = appJustInverse (Just (::) <*> check x t) (checkAll x ts) prf in - let 0 w = appJustInverse (Just (::)) (check x t) (fst z.snd.snd) in - Calc $ - |~ t :: ts - ~~ map (pure (thin x) <$>) (w.snd.fst :: z.snd.fst) ...(cong2 (::) (checkJust x t (fst $ snd w.snd.snd)) (checkAllJust x ts (fst $ snd z.snd.snd))) - ~~ map (pure (thin x) <$>) (w.fst w.snd.fst z.snd.fst) ...(cong (\f => map (pure (thin x) <$>) (f w.snd.fst z.snd.fst)) $ injective $ fst w.snd.snd) - ~~ map (pure (thin x) <$>) (z.fst z.snd.fst) ...(sym $ cong (\f => map (pure (thin x) <$>) (f z.snd.fst)) $ snd $ snd w.snd.snd) - ~~ map (pure (thin x) <$>) us ...(sym $ cong (map (pure (thin x) <$>)) $ snd $ snd z.snd.snd) +checkProof : {k : Nat} -> (x : Fin (S k)) -> (t : Term sig (S k)) -> CheckProof x t (check x t) +checkAllProof : + {k : Nat} -> + (x : Fin (S k)) -> + (ts : Vect n (Term sig (S k))) -> + CheckAllProof x ts (checkAll x ts) + +checkProof x (Var y) with (thickProof x y) + checkProof x (Var x) | Equal prf = Occurs Top (cong (Var <$>) prf) + checkProof x (Var _) | Thinned y prf = Stronger (Var y) (cong (Var <$>) prf) +checkProof x (Op op ts) with (checkAllProof x ts) + checkProof x (Op op _) | OccursAt i ts zip prf = Occurs (Op op i ts zip) (cong (Op op <$>) prf) + checkProof x (Op op _) | AllStronger ts prf = Stronger (Op op ts) (cong (Op op <$>) prf) + +checkAllProof x [] = AllStronger [] Refl +checkAllProof x (t :: ts) with (checkProof x t) + checkAllProof x (_ :: ts) | Occurs zip prf = + OccursAt FZ ts zip (cong (\t => [| t :: checkAll x ts |]) prf) + checkAllProof x (_ :: ts) | Stronger u prf with (checkAllProof x ts) + checkAllProof x (_ :: _) | Stronger u prf | OccursAt i ts zip prf' = + OccursAt (FS i) (_ :: ts) zip (cong2 (\t, ts => [| t :: ts |]) prf prf') + checkAllProof x (_ :: _) | Stronger u prf | AllStronger us prf' = + AllStronger (u :: us) (cong2 (\t, ts => [| t :: ts |]) prf prf') -- Single Variable Substitution ------------------------------------------------ export -for : Term sig (pred k) -> SFin k -> SFin k -> Term sig (pred k) -(t `for` x) y = maybe t Var' (thick x y) +for : {k : Nat} -> Term sig k -> Fin (S k) -> Fin (S k) -> Term sig k +(t `for` x) y = maybe t Var (thick x y) export forRefl : - (0 u : Term sig (pred k)) -> - (x : SFin k) -> + (0 u : Term sig k) -> + (x : Fin (S k)) -> (u `for` x) x = u -forRefl u x = cong (maybe u Var') $ extractIsNothing $ thickRefl x +forRefl u x = cong (maybe u Var) $ thickRefl x export forThin : - (0 t : Term sig (pred k)) -> - (x : SFin k) -> - (t `for` x) . thin x .=. Var' -forThin t x i = cong (maybe t Var') (thickThin x i) + (0 t : Term sig k) -> + (x : Fin (S k)) -> + (t `for` x) . thin x .=. Var +forThin t x i = cong (maybe t Var) (thickThin x i) export forUnifies : - (x : SFin k) -> + (x : Fin (S k)) -> (t : Term sig k) -> - (0 _ : check x t = Just u) -> - (u `for` x) <$> t = (u `for` x) <$> Var' x -forUnifies x t prf = Calc $ - |~ (u `for` x) <$> t - ~~ (u `for` x) <$> pure (thin x) <$> u ...(cong ((u `for` x) <$>) $ checkJust x t prf) - ~~ (u `for` x) . thin x <$> u ...(sym $ subAssoc (u `for` x) (pure (thin x)) u) - ~~ Var' <$> u ...(subCong (forThin u x) u) - ~~ u ...(subUnit u) - ~~ (u `for` x) <$> Var' x ...(sym $ forRefl u x) + (t `for` x) <$> pure (thin x) <$> t = (t `for` x) <$> Var x +forUnifies x t = Calc $ + |~ (t `for` x) <$> pure (thin x) <$> t + ~~ (t `for` x) . thin x <$> t ...(sym $ subAssoc (t `for` x) (pure (thin x)) t) + ~~ Var <$> t ...(subExtensional (forThin t x) t) + ~~ t ...(subUnit t) + ~~ (t `for` x) <$> Var x ...(sym $ forRefl t x) -- Substitution List ----------------------------------------------------------- public export data AList : Signature -> Nat -> Nat -> Type where Lin : AList sig n n - (:<) : AList sig k n -> (Term sig k, SFin (S k)) -> AList sig (S k) n + (:<) : AList sig k n -> (Term sig k, Fin (S k)) -> AList sig (S k) n %name AList sub namespace Exists public export - (:<) : Exists (AList sig n) -> (Term sig n, SFin (S n)) -> Exists (AList sig (S n)) + (:<) : Exists (AList sig n) -> (Term sig n, Fin (S n)) -> Exists (AList sig (S n)) Evidence _ sub :< tx = Evidence _ (sub :< tx) export -eval : AList sig k n -> SFin k -> Term sig n -eval [<] = Var' +eval : {k : Nat} -> AList sig k n -> Fin k -> Term sig n +eval [<] = Var eval (sub :< (t, x)) = eval sub . (t `for` x) export @@ -199,11 +124,6 @@ sub ++ sub1 :< tx = (sub ++ sub1) :< tx -- Properties export -recover : Singleton k -> AList sig k n -> Singleton n -recover x [<] = x -recover x (sub :< _) = recover (pure pred <*> x) sub - -export evalHomo : (0 sub2 : AList sig k n) -> (sub1 : AList sig j k) -> @@ -211,7 +131,7 @@ evalHomo : evalHomo sub2 [<] i = Refl evalHomo sub2 (sub1 :< (t, x)) i = Calc $ |~ eval (sub2 ++ sub1) <$> (t `for` x) i - ~~ (eval sub2 . eval sub1) <$> (t `for` x) i ...(subCong (evalHomo sub2 sub1) ((t `for` x) i)) + ~~ (eval sub2 . eval sub1) <$> (t `for` x) i ...(subExtensional (evalHomo sub2 sub1) ((t `for` x) i)) ~~ eval sub2 <$> eval sub1 <$> (t `for` x) i ...(subAssoc (eval sub2) (eval sub1) ((t `for` x) i)) export @@ -233,180 +153,208 @@ appendAssoc sub3 sub2 (sub1 :< tx) = cong (:< tx) (appendAssoc sub3 sub2 sub1) coerce : {0 op, op' : sig.Op} -> op = op' -> Vect op'.fst a -> Vect op.fst a coerce Refl = id -flexFlex : SFin (S n) -> SFin (S n) -> Exists (AList sig (S n)) -flexFlex x y = case thick x y of - Just z => Evidence _ [<(Var' z, x)] - Nothing => Evidence _ [<] +flexFlex : {n : Nat} -> Fin n -> Fin n -> (k ** AList sig n k) +flexFlex {n = S n} x y = case thick x y of + Just z => (_ **[<(Var z, x)]) + Nothing => (_ ** [<]) -flexRigid : SFin (S n) -> Term sig (S n) -> Maybe (Exists (AList sig (S n))) -flexRigid x t = case check x t of +flexRigid : {n : Nat} -> Fin n -> Term sig n -> Maybe (Exists (AList sig n)) +flexRigid {n = S n} x t = case check x t of Just u => Just (Evidence _ [<(u, x)]) Nothing => Nothing export amgu : DecOp sig => + {n : Nat} -> (t, u : Term sig n) -> - Exists (AList sig n) -> + AList sig n k -> Maybe (Exists (AList sig n)) amguAll : DecOp sig => - (ts, us : Vect k (Term sig n)) -> - Exists (AList sig n) -> + {n : Nat} -> + (ts, us : Vect j (Term sig n)) -> + AList sig n k -> Maybe (Exists (AList sig n)) amgu (Op op ts) (Op op' us) acc with (decOp (Evidence _ op) (Evidence _ op')) amgu (Op op ts) (Op op us) acc | Yes Refl = amguAll ts us acc _ | No neq = Nothing -amgu (Var x) (Var y) (Evidence _ [<]) = Just (flexFlex x y) -amgu (Var x) (Op op' us) (Evidence _ [<]) = flexRigid x (Op op' us) -amgu (Op op ts) (Var y) (Evidence _ [<]) = flexRigid y (Op op ts) -amgu t@(Var _) u@(Var _) (Evidence _ (sub :< (v, z))) = - (:< (v, z)) <$> amgu ((v `for` z) <$> t) ((v `for` z) <$> u) (Evidence _ sub) -amgu t@(Var _) u@(Op _ _) (Evidence _ (sub :< (v, z))) = - (:< (v, z)) <$> amgu ((v `for` z) <$> t) ((v `for` z) <$> u) (Evidence _ sub) -amgu t@(Op _ _) u@(Var _) (Evidence _ (sub :< (v, z))) = - (:< (v, z)) <$> amgu ((v `for` z) <$> t) ((v `for` z) <$> u) (Evidence _ sub) - -amguAll [] [] acc = Just acc +amgu (Var x) (Var y) [<] = Just (Evidence _ (flexFlex x y).snd) +amgu (Var x) (Op op' us) [<] = flexRigid x (Op op' us) +amgu (Op op ts) (Var y) [<] = flexRigid y (Op op ts) +amgu t@(Var _) u@(Var _) (sub :< (v, z)) = + (:< (v, z)) <$> amgu ((v `for` z) <$> t) ((v `for` z) <$> u) sub +amgu t@(Var _) u@(Op _ _) (sub :< (v, z)) = + (:< (v, z)) <$> amgu ((v `for` z) <$> t) ((v `for` z) <$> u) sub +amgu t@(Op _ _) u@(Var _) (sub :< (v, z)) = + (:< (v, z)) <$> amgu ((v `for` z) <$> t) ((v `for` z) <$> u) sub + +amguAll [] [] acc = Just (Evidence _ acc) amguAll (t :: ts) (u :: us) acc = do acc <- amgu t u acc - amguAll ts us acc + amguAll ts us acc.snd export -mgu : DecOp sig => (t, u : Term sig n) -> Maybe (Exists (AList sig n)) -mgu t u = amgu t u (Evidence _ [<]) +mgu : DecOp sig => {n : Nat} -> (t, u : Term sig n) -> Maybe (Exists (AList sig n)) +mgu t u = amgu t u [<] -- Properties export trivialUnify : - (0 f : SFin n -> Term sig k) -> + (0 f : Fin n -> Term sig k) -> (t : Term sig n) -> - (Max (Extension (Unifies t t) f)).Prop Var' + (Max (Extension (Unifies t t) f)).Prop Var trivialUnify f t = (Refl , \g, prf => varMax g) export varElim : - (x : SFin (S n)) -> - (t : Term sig (S n)) -> - (0 _ : check x t = Just u) -> - (Max (Unifies (Var x) t)).Prop (u `for` x) -varElim x t prf = - ( sym $ forUnifies x t prf - , \g, prf' => MkLte (g . thin x) (\i => - case decEq x i of - Yes Refl => - Calc $ - |~ g x - ~~ g <$> t ...(prf') - ~~ g <$> pure (thin x) <$> u ...(cong (g <$>) $ checkJust i t prf) - ~~ (g . thin x) <$> u ...(sym $ subAssoc g (pure (thin x)) u) - ~~ (g . thin x) <$> (u `for` x) x ..<(cong ((g . thin x) <$>) $ forRefl u x) - No neq => - let isJust = thickNeq x i neq in - let (y ** thickIsJustY) = extractIsJust isJust in - let thinXYIsI = thickJust x i thickIsJustY in - Calc $ - |~ g i - ~~ g (thin x y) ..<(cong g thinXYIsI) - ~~ (g . thin x) <$> Var' y ...(Refl) - ~~ (g . thin x) <$> (u `for` x) (thin x y) ..<(cong ((g . thin x) <$>) $ forThin u x y) - ~~ (g . thin x) <$> (u `for` x) i ...(cong (((g . thin x) <$>) . (u `for` x)) $ thinXYIsI)) + {n : Nat} -> + (x : Fin (S n)) -> + (t : Term sig n) -> + (Max (Unifies (Var x) (pure (thin x) <$> t))).Prop (t `for` x) +varElim x t = + ( sym $ forUnifies x t + , \g, prf' => MkLte (g . thin x) (lteProof g prf') ) + where + lteProof : + forall k. + (g : Fin (S n) -> Term sig k) -> + (Unifies (Var x) (pure (thin x) <$> t)).Prop g -> + g .=. (g . thin x) . (t `for` x) + lteProof g prf i with (thickProof x i) + lteProof g prf _ | Equal prf' = Calc $ + |~ g x + ~~ g <$> pure (thin x) <$> t ...(prf) + ~~ g . thin x <$> t ..<(subAssoc g (pure (thin x)) t) + ~~ g . thin x <$> (t `for` x) x ..<(cong ((g . thin x <$>) . maybe t Var) prf') + lteProof g prf _ | Thinned i prf' = sym $ cong (g . thin x <$>) (forThin t x i) flexFlexUnifies : - (x, y : SFin (S n)) -> + {n : Nat} -> + (x, y : Fin n) -> (Max {sig} (Unifies (Var x) (Var y))).Prop (eval (flexFlex x y).snd) -flexFlexUnifies x y with (thick x y) proof prf - _ | Just z = - (Max (Unifies (Var x) (Var y))).cong - (\i => sym $ subUnit ((Var' z `for` x) i)) - (varElim x (Var y) (cong (map Var') prf)) - _ | Nothing = - rewrite thickNothing x y (rewrite prf in ItIsNothing) in - trivialUnify Var' (Var y) - -flexRigidUnifies : - (x : SFin (S n)) -> - (t : Term sig (S n)) -> - (0 _ : flexRigid x t = Just sub) -> - (Max (Unifies (Var x) t)).Prop (eval sub.snd) -flexRigidUnifies x t ok with (check x t) proof prf - flexRigidUnifies x t Refl | Just u = - (Max (Unifies (Var x) t)).cong - (\i => sym $ subUnit ((u `for` x) i)) - (varElim x t prf) - -flexRigidFails : - (x : SFin (S k)) -> - (op : sig.Operator j) -> - (ts : Vect j (Term sig (S k))) -> - (0 _ : IsNothing (flexRigid x (Op op ts))) -> - Nothing (Unifies (Var x) (Op op ts)) -flexRigidFails x op ts isNothing f prf' with (check x (Op op ts)) proof prf - _ | Nothing = - let - (zip ** occurs) = checkNothing x (Op op ts) (rewrite prf in ItIsNothing) - cycle : (f x = (f <$> zip) + f x) - cycle = Calc $ - |~ f x - ~~ f <$> Op op ts ...(prf') - ~~ f <$> zip + Var x ...(cong (f <$>) occurs) - ~~ (f <$> zip) + f x ...(actionHomo f zip (Var x)) - zipIsTop : (zip = Top) - zipIsTop = invertActionTop zip $ noCycles (f <$> zip) (f x) (sym cycle) - opIsVar : (Op op ts = Var x) - opIsVar = trans occurs (cong (+ Var x) zipIsTop) - in - absurd opIsVar +flexFlexUnifies {n = S n} x y with (thickProof x y) + flexFlexUnifies {n = S n} x _ | Equal prf = + rewrite prf in + trivialUnify Var (Var x) + flexFlexUnifies {n = S n} x _ | Thinned y prf = + rewrite prf in + (Max (Unifies (Var x) (Var _))).cong + (\i => sym $ subUnit ((Var y `for` x) i)) + (varElim x (Var y)) + +data FlexRigidProof : Fin n -> Term sig n -> Maybe (Exists (AList sig n)) -> Type where + NoUnifier : Nothing (Unifies (Var x) t) -> res = Nothing -> FlexRigidProof x t res + ElimVar : + {n : Nat} -> + (sub : AList sig k n) -> + (mgu : (Max (Unifies (Var x) t)).Prop (eval sub)) -> + res = Just (Evidence _ sub) -> + FlexRigidProof x t res + +flexRigidProof : + {n : Nat} -> + (x : Fin n) -> + (op : sig.Operator k) -> + (ts : Vect k (Term sig n)) -> + FlexRigidProof x (Op op ts) (flexRigid x (Op op ts)) +flexRigidProof {n = S n} x op ts with (checkProof x (Op op ts)) + flexRigidProof x op _ | Occurs zip@(Op op i ts zip') prf = + rewrite prf in + NoUnifier + (\f, prf' => + let + cycle : (f x = (f <$> zip) + f x) + cycle = Calc $ + |~ f x + ~~ f <$> Op op _ ...(prf') + ~~ (f <$> zip) + f x ...(actionHomo f zip (Var x)) + + zipIsTop : (zip = Top) + zipIsTop = invertActionTop zip $ noCycles (f <$> zip) (f x) (sym cycle) + + opIsVar : Op op (insertAt i (zip' + Var x) ts) = Var x + opIsVar = cong (+ Var x) zipIsTop + in + absurd opIsVar) + Refl + flexRigidProof x op _ | Stronger (Op op us) prf = + rewrite prf in + ElimVar + [<(Op op us, x)] + ((Max (Unifies (Var x) (Op op _))).cong + (\i => sym $ subUnit ((Op op us `for` x) i)) + (varElim x (Op op us))) + Refl stepEquiv : + {k : Nat} -> (t, u : Term sig (S k)) -> (sub : AList sig k j) -> (v : Term sig k) -> - (x : SFin (S k)) -> + (x : Fin (S k)) -> Extension (Unifies t u) (eval (sub :< (v, x))) <=> Extension (Unifies ((v `for` x) <$> t) ((v `for` x) <$> u)) (eval sub) stepEquiv t u sub v x = extendUnify t u (v `for` x) (eval sub) parameters {auto _ : DecOp sig} public export - data AmguProof : (t, u : Term sig k) -> Exists (AList sig k) -> Type where - Success : - {0 sub : Exists (AList sig k)} -> - (sub' : Exists (AList sig sub.fst)) -> - (Max (Extension (Unifies t u) (eval sub.snd))).Prop (eval sub'.snd) -> - amgu t u sub = Just (Evidence sub'.fst (sub'.snd ++ sub.snd)) -> - AmguProof t u sub + data AmguProof : + Term sig k -> + Term sig k -> + AList sig k n -> + Maybe (Exists (AList sig k)) -> + Type + where Failure : - {0 sub : Exists (AList sig k)} -> - Nothing (Extension (Unifies t u) (eval sub.snd)) -> - IsNothing (amgu t u sub) -> - AmguProof t u sub + Nothing (Extension (Unifies t u) (eval sub)) -> + res = Nothing -> + AmguProof t u sub res + Success : + {j : Nat} -> + {0 sub : AList sig k n} -> + (sub' : AList sig n j) -> + (Max (Extension (Unifies t u) (eval sub))).Prop (eval sub') -> + res = Just (Evidence _ (sub' ++ sub)) -> + AmguProof t u sub res public export - data AmguAllProof : (ts, us : Vect n (Term sig k)) -> Exists (AList sig k) -> Type where - SuccessAll : - {0 sub : Exists (AList sig k)} -> - (sub' : Exists (AList sig sub.fst)) -> - (Max (Extension (UnifiesAll ts us) (eval sub.snd))).Prop (eval sub'.snd) -> - amguAll ts us sub = Just (Evidence sub'.fst (sub'.snd ++ sub.snd)) -> - AmguAllProof ts us sub + data AmguAllProof : + Vect j (Term sig k) -> + Vect j (Term sig k) -> + AList sig k n -> + Maybe (Exists (AList sig k)) -> + Type + where FailureAll : - {0 sub : Exists (AList sig k)} -> - Nothing (Extension (UnifiesAll ts us) (eval sub.snd)) -> - IsNothing (amguAll ts us sub) -> - AmguAllProof ts us sub + Nothing (Extension (UnifiesAll ts us) (eval sub)) -> + res = Nothing -> + AmguAllProof ts us sub res + SuccessAll : + {j : Nat} -> + {0 sub : AList sig k n} -> + (sub' : AList sig n j) -> + (Max (Extension (UnifiesAll ts us) (eval sub))).Prop (eval sub') -> + res = Just (Evidence _ (sub' ++ sub)) -> + AmguAllProof ts us sub res export -amguProof : DecOp sig => (t, u : Term sig n) -> (sub : Exists (AList sig n)) -> AmguProof t u sub +amguProof : + DecOp sig => + {k, n : Nat} -> + (t, u : Term sig k) -> + (sub : AList sig k n) -> + AmguProof t u sub (amgu t u sub) export amguAllProof : DecOp sig => - (ts, us : Vect k (Term sig n)) -> - (sub : Exists (AList sig n)) -> - AmguAllProof ts us sub + {k, n : Nat} -> + (ts, us : Vect j (Term sig k)) -> + (sub : AList sig k n) -> + AmguAllProof ts us sub (amguAll ts us sub) amguProof (Op op ts) (Op op' us) sub with (decOp (Evidence _ op) (Evidence _ op')) proof prf amguProof (Op op ts) (Op op us) sub | Yes Refl @@ -414,53 +362,48 @@ amguProof (Op op ts) (Op op' us) sub with (decOp (Evidence _ op) (Evidence _ op' _ | SuccessAll sub' val prf' = let cong : - Max (Extension (Unifies (Op op ts) (Op op us)) (eval sub.snd)) <=> - Max (Extension (UnifiesAll ts us) (eval sub.snd)) - cong = maxCong $ extendCong (eval sub.snd) $ unifiesOp op ts us + Max (Extension (Unifies (Op op ts) (Op op us)) (eval sub)) <=> + Max (Extension (UnifiesAll ts us) (eval sub)) + cong = maxCong $ extendCong (eval sub) $ unifiesOp op ts us in Success sub' - (cong.rightToLeft (eval sub'.snd) val) - (rewrite prf in prf') + (cong.rightToLeft (eval sub') val) + prf' _ | FailureAll absurd prf' = Failure - (nothingEquiv (symmetric $ extendCong (eval sub.snd) $ unifiesOp op ts us) absurd) - (rewrite prf in prf') + (nothingEquiv (symmetric $ extendCong (eval sub) $ unifiesOp op ts us) absurd) + prf' _ | No neq = Failure (\f, prf => neq $ opInjectiveOp prf) - (rewrite prf in ItIsNothing) -amguProof (Var x) (Var y) (Evidence _ [<]) with (thick x y) proof prf - _ | Just z = Success (flexFlex x y) (flexFlexUnifies x y) (rewrite prf in Refl) - _ | Nothing = Success (flexFlex x y) (flexFlexUnifies x y) (rewrite prf in Refl) -amguProof (Var x) (Op op' us) (Evidence _ [<]) with (flexRigid x (Op op' us)) proof prf - _ | Just sub@(Evidence _ _) = Success sub (flexRigidUnifies x (Op op' us) prf) prf - _ | Nothing = - Failure - (flexRigidFails x op' us (rewrite prf in ItIsNothing)) - (rewrite prf in ItIsNothing) -amguProof (Op op ts) (Var y) (Evidence _ [<]) with (flexRigid y (Op op ts)) proof prf - _ | Just sub@(Evidence _ sub') = + Refl +amguProof (Var x) (Var y) [<] = + Success + (flexFlex x y).snd + (flexFlexUnifies x y) + Refl +amguProof (Var x) (Op op' us) [<] with (flexRigidProof x op' us) + _ | NoUnifier absurd prf = Failure absurd prf + _ | ElimVar sub val prf = Success sub val prf +amguProof (Op op ts) (Var y) [<] with (flexRigidProof y op ts) + _ | NoUnifier absurd prf = let cong : - Max (Extension (Unifies (Var y) (Op op ts)) Var') <=> - Max (Extension (Unifies (Op op ts) (Var y)) Var') - cong = maxCong $ extendCong Var' $ unifiesSym (Var y) (Op op ts) + Nothing (Extension (Unifies (Var y) (Op op ts)) Var) -> + Nothing (Extension (Unifies (Op op ts) (Var y)) Var) + cong = nothingEquiv $ extendCong Var $ unifiesSym (Var y) (Op op ts) in - Success sub - (cong.leftToRight (eval sub.snd) (flexRigidUnifies y (Op op ts) prf)) - prf - _ | Nothing = + Failure (cong absurd) prf + _ | ElimVar sub val prf = let cong : - Nothing (Extension (Unifies (Var y) (Op op ts)) Var') -> - Nothing (Extension (Unifies (Op op ts) (Var y)) Var') - cong = nothingEquiv $ extendCong Var' $ unifiesSym (Var y) (Op op ts) + Max (Extension (Unifies (Var y) (Op op ts)) Var) <=> + Max (Extension (Unifies (Op op ts) (Var y)) Var) + cong = maxCong $ extendCong Var $ unifiesSym (Var y) (Op op ts) in - Failure - (cong $ flexRigidFails y op ts (rewrite prf in ItIsNothing)) - (rewrite prf in ItIsNothing) -amguProof (Var x) (Var y) (Evidence l (sub :< (v, z))) - with (amguProof ((v `for` z) x) ((v `for` z) y) (Evidence _ sub)) + Success sub (cong.leftToRight _ val) prf +amguProof (Var x) (Var y) (sub :< (v, z)) + with (amguProof ((v `for` z) x) ((v `for` z) y) sub) _ | Success sub' val prf = let cong' : @@ -469,14 +412,14 @@ amguProof (Var x) (Var y) (Evidence l (sub :< (v, z))) cong' = maxCong $ stepEquiv (Var x) (Var y) sub v z in Success sub' - (cong'.rightToLeft (eval sub'.snd) val) + (cong'.rightToLeft (eval sub') val) (cong (map (:< (v, z))) prf) _ | Failure absurd prf = Failure (nothingEquiv (symmetric $ stepEquiv (Var x) (Var y) sub v z) absurd) - (mapNothing (:< (v, z)) prf) -amguProof (Var x) (Op op' us) (Evidence _ (sub :< (v, z))) - with (amguProof ((v `for` z) x) ((v `for` z) <$> Op op' us) (Evidence _ sub)) + (rewrite prf in Refl) +amguProof (Var x) (Op op' us) (sub :< (v, z)) + with (amguProof ((v `for` z) x) ((v `for` z) <$> Op op' us) sub) _ | Success sub' val prf = let cong' : @@ -485,14 +428,14 @@ amguProof (Var x) (Op op' us) (Evidence _ (sub :< (v, z))) cong' = maxCong $ stepEquiv (Var x) (Op op' us) sub v z in Success sub' - (cong'.rightToLeft (eval sub'.snd) val) + (cong'.rightToLeft (eval sub') val) (cong (map (:< (v, z))) prf) _ | Failure absurd prf = Failure (nothingEquiv (symmetric $ stepEquiv (Var x) (Op op' us) sub v z) absurd) - (mapNothing (:< (v, z)) prf) -amguProof (Op op ts) (Var y) (Evidence _ (sub :< (v, z))) - with (amguProof ((v `for` z) <$> Op op ts) ((v `for` z) y) (Evidence _ sub)) + (rewrite prf in Refl) +amguProof (Op op ts) (Var y) (sub :< (v, z)) + with (amguProof ((v `for` z) <$> Op op ts) ((v `for` z) y) sub) _ | Success sub' val prf = let cong' : @@ -501,38 +444,38 @@ amguProof (Op op ts) (Var y) (Evidence _ (sub :< (v, z))) cong' = maxCong $ stepEquiv (Op op ts) (Var y) sub v z in Success sub' - (cong'.rightToLeft (eval sub'.snd) val) + (cong'.rightToLeft (eval sub') val) (cong (map (:< (v, z))) prf) _ | Failure absurd prf = Failure (nothingEquiv (symmetric $ stepEquiv (Op op ts) (Var y) sub v z) absurd) - (mapNothing (:< (v, z)) prf) + (rewrite prf in Refl) -amguAllProof [] [] (Evidence _ sub) = - SuccessAll (Evidence _ [<]) +amguAllProof [] [] sub = + SuccessAll [<] ([], \g, x => varMax g) (sym $ cong (\sub => Just (Evidence _ sub)) $ appendUnitLeft sub) amguAllProof (t :: ts) (u :: us) sub with (amguProof t u sub) - _ | Success sub' val prf with (amguAllProof ts us (Evidence _ (sub'.snd ++ sub.snd))) + _ | Success sub' val prf with (amguAllProof ts us (sub' ++ sub)) _ | SuccessAll sub'' val' prf' = let cong' = maxCong $ - extendCong2 (evalHomo sub'.snd sub.snd) (reflexive {x = UnifiesAll ts us}) + extendCong2 (evalHomo sub' sub) (reflexive {x = UnifiesAll ts us}) opt = optimistLemma (unifiesDClosed t u) val $ - cong'.leftToRight (eval sub''.snd) val' + cong'.leftToRight (eval sub'') val' in - SuccessAll (Evidence _ (sub''.snd ++ sub'.snd)) - ((Max (Extension (UnifiesAll (t :: ts) (u :: us)) (eval sub.snd))).cong - (\i => sym $ evalHomo sub''.snd sub'.snd i) + SuccessAll (sub'' ++ sub') + ((Max (Extension (UnifiesAll (t :: ts) (u :: us)) (eval sub))).cong + (\i => sym $ evalHomo sub'' sub' i) opt) (rewrite prf in rewrite prf' in - cong (\sub => Just (Evidence sub''.fst sub)) $ - appendAssoc sub''.snd sub'.snd sub.snd) + cong (\sub => Just (Evidence _ sub)) $ + appendAssoc sub'' sub' sub) _ | FailureAll absurd prf' = let - cong' = extendCong2 (evalHomo sub'.snd sub.snd) (reflexive {x = UnifiesAll ts us}) + cong' = extendCong2 (evalHomo sub' sub) (reflexive {x = UnifiesAll ts us}) in FailureAll (failTail val $ nothingEquiv cong' absurd) @@ -540,24 +483,24 @@ amguAllProof (t :: ts) (u :: us) sub with (amguProof t u sub) _ | Failure absurd prf = FailureAll (failHead absurd) - (bindNothing prf (amguAll ts us)) + (rewrite prf in Refl) parameters {auto _ : DecOp sig} namespace MguProof public export - data MguProof : (t, u : Term sig k) -> Type where + data MguProof : (t, u : Term sig k) -> Maybe (Exists (AList sig k)) -> Type where Success : - (sub : Exists (AList sig k)) -> - (Max (Unifies t u)).Prop (eval sub.snd) -> - mgu t u = Just sub -> - MguProof t u + (sub : AList sig k n) -> + (Max (Unifies t u)).Prop (eval sub) -> + res = Just (Evidence _ sub) -> + MguProof t u res Failure : Nothing (Unifies t u) -> - IsNothing (mgu t u) -> - MguProof t u + res = Nothing -> + MguProof t u res export -mguProof : DecOp sig => (t, u : Term sig k) -> MguProof t u -mguProof t u with (amguProof t u (Evidence _ [<])) - _ | Success (Evidence _ sub) val prf = Success (Evidence _ sub) val prf +mguProof : DecOp sig => {k : Nat} -> (t, u : Term sig k) -> MguProof t u (mgu t u) +mguProof t u with (amguProof t u [<]) + _ | Success sub val prf = Success sub val prf _ | Failure absurd prf = Failure absurd prf |