diff options
author | Greg Brown <greg.brown01@ed.ac.uk> | 2024-01-22 12:05:20 +0000 |
---|---|---|
committer | Greg Brown <greg.brown01@ed.ac.uk> | 2024-01-22 12:05:20 +0000 |
commit | 09cd77b9a880559f7f00f710d9a0b56df04fe807 (patch) | |
tree | 888abb0f0769aada5077e8efb4a0b4d2a00fb215 | |
parent | 9c73520c5fe209cfd3d212b5891dfb8b677fb9d4 (diff) |
-rw-r--r-- | src/Data/Term.idr | 62 | ||||
-rw-r--r-- | src/Data/Term/Property.idr | 44 | ||||
-rw-r--r-- | src/Data/Term/Unify.idr | 84 |
3 files changed, 147 insertions, 43 deletions
diff --git a/src/Data/Term.idr b/src/Data/Term.idr index 973ff3d..bfeb360 100644 --- a/src/Data/Term.idr +++ b/src/Data/Term.idr @@ -2,7 +2,10 @@ module Data.Term import public Data.DPair import public Data.Vect + +import Data.Fin.Extra import Data.Vect.Properties.Map + import Syntax.PreorderReasoning %prefix_record_projections off @@ -88,12 +91,20 @@ subAssoc f g (Op op ts) = cong (Op op) $ Calc $ export subComp : - (f : Fin k -> Term sig n) -> - (r : Fin j -> Fin k) -> + (0 f : Fin k -> Term sig n) -> + (0 r : Fin j -> Fin k) -> f . pure r .=. f . r subComp f r i = Refl export +subAssoc' : + (f : Fin k -> Term sig n) -> + (g : Fin j -> Fin k) -> + (t : Term sig j) -> + (f . g) <$> t = f <$> pure g <$> t +subAssoc' f g = subAssoc f (Var . g) + +export compCong2 : {0 f1, f2 : Fin k -> Term sig n} -> {0 g1, g2 : Fin j -> Term sig k} -> @@ -119,6 +130,53 @@ compCongR : f . g1 .=. f . g2 compCongR f prf = compCong2 (\_ => Refl) prf +-- Substitution is a Semigroupoid ---------------------------------------------- + +export +(++) : + {j : Nat} -> + (Fin j -> Term sig n) -> + (Fin k -> Term sig n) -> + Fin (j + k) -> Term sig n +f ++ g = either f g . splitSum + +export +appendWeakenN : + {j : Nat} -> + (0 f : Fin j -> Term sig n) -> + (0 g : Fin k -> Term sig n) -> + (f ++ g) . weakenN k .=. f +appendWeakenN f g i = cong (either f g) $ splitSumOfWeakenN i + +export +appendShift : + {j : Nat} -> + (0 f : Fin j -> Term sig n) -> + (0 g : Fin k -> Term sig n) -> + (f ++ g) . shift j .=. g +appendShift f g i = cong (either f g) $ splitSumOfShift i + +export +appendCong2 : + {j : Nat} -> + {0 f : Fin j -> Term sig n} -> + {0 g : Fin k -> Term sig n} -> + {0 h : Fin (j + k) -> Term sig n} -> + h . weakenN k .=. f -> + h . shift j .=. g -> + h .=. f ++ g +appendCong2 prf1 prf2 x with (splitSum x) proof prf + _ | Left i = Calc $ + |~ h x + ~~ h (indexSum (splitSum x)) ..<(cong h (indexOfSplitSumInverse x)) + ~~ h (weakenN k i) ...(cong (h . indexSum) prf) + ~~ f i ...(prf1 i) + _ | Right i = Calc $ + |~ h x + ~~ h (indexSum (splitSum x)) ..<(cong h (indexOfSplitSumInverse x)) + ~~ h (shift j i) ...(cong (h . indexSum) prf) + ~~ g i ...(prf2 i) + -- Injectivity ----------------------------------------------------------------- export diff --git a/src/Data/Term/Property.idr b/src/Data/Term/Property.idr index 62f4caa..958c1c2 100644 --- a/src/Data/Term/Property.idr +++ b/src/Data/Term/Property.idr @@ -232,8 +232,8 @@ transitive prf1 prf2 = MkLte } export -varMax : (f : Fin k -> Term sig m) -> f <= Var -varMax f = MkLte f (\i => Refl) +varUniqueMax : (f : Fin k -> Term sig m) -> f <= Var +varUniqueMax f = MkLte f (\i => Refl) export compLte : f <= g -> (h : Fin k -> Term sig m) -> f . h <= g . h @@ -255,6 +255,34 @@ lteExtend : (Extension p g).Prop prf.sub lteExtend prf x = p.cong _ _ prf.prf x +-- Maximal --------------------------------------------------------------------- + +public export +record Maximal (p : Property sig k) (f : Fin k -> Term sig n) where + constructor MkMaximal + valid : p.Prop f + universal : forall j. (g : Fin k -> Term sig j) -> p.Prop g -> Fin n -> Term sig j + factors : + forall j. + (g : Fin k -> Term sig j) -> + (v : p.Prop g) -> + g .=. universal g v . f + +public export +Max : Property sig k -> Property sig k +Max p = MkProp + { Prop = Maximal p + , cong = \f, g, prf, mg => + MkMaximal + { valid = p.cong f g prf mg.valid + , universal = mg.universal + , factors = \h, v, x => Calc $ + |~ h x + ~~ mg.universal h v <$> f x ...(mg.factors h v x) + ~~ mg.universal h v <$> g x ...(compCongR (mg.universal h v) prf x) + } + } + -- Most General ---------------------------------------------------------------- public export @@ -278,6 +306,10 @@ record MostGeneral (p : Property sig k) (f : Fin k -> Term sig n) where %name MostGeneral mg export +mostGeneralIsMaximal : MostGeneral p f -> Maximal p f +mostGeneralIsMaximal mg = MkMaximal mg.valid mg.universal mg.factors + +export varMostGeneral : p.Prop Var -> MostGeneral p Var varMostGeneral v = MkMostGeneral @@ -288,8 +320,8 @@ varMostGeneral v = } public export -Max : Property sig k -> Property sig k -Max p = MkProp +UniqueMax : Property sig k -> Property sig k +UniqueMax p = MkProp { Prop = MostGeneral p , cong = \f, g, prf, mg => MkMostGeneral @@ -309,7 +341,7 @@ Max p = MkProp } export -maxCong : p <=> q -> Max p <=> Max q +maxCong : p <=> q -> UniqueMax p <=> UniqueMax q maxCong prf = MkEquivalence { leftToRight = \f, mg => MkMostGeneral @@ -429,7 +461,7 @@ failTail : {ps : Vect _ (Property sig j)} -> {a : Fin j -> Term sig k} -> {f : Fin k -> Term sig m} -> - (Max (Extension p a)).Prop f -> + (UniqueMax (Extension p a)).Prop f -> Nothing (Extension (All ps) (f . a)) -> Nothing (Extension (All (p :: ps)) a) failTail mg absurd g (v :: vs) = diff --git a/src/Data/Term/Unify.idr b/src/Data/Term/Unify.idr index 9f806fa..113514a 100644 --- a/src/Data/Term/Unify.idr +++ b/src/Data/Term/Unify.idr @@ -148,8 +148,8 @@ data AList : Signature -> Nat -> Nat -> Type where namespace Exists public export - (:<) : Exists (AList sig n) -> (Term sig n, Fin (S n)) -> Exists (AList sig (S n)) - Evidence _ sub :< tx = Evidence _ (sub :< tx) + (:<) : (k ** AList sig n k) -> (Term sig n, Fin (S n)) -> (k ** AList sig (S n) k) + (_ ** sub) :< tx = (_ ** sub :< tx) export eval : {k : Nat} -> AList sig k n -> Fin k -> Term sig n @@ -198,29 +198,29 @@ flexFlex {n = S n} x y = case thick x y of Just z => (_ **[<(Var z, x)]) Nothing => (_ ** [<]) -flexRigid : {n : Nat} -> Fin n -> Term sig n -> Maybe (Exists (AList sig n)) +flexRigid : {n : Nat} -> Fin n -> Term sig n -> Maybe (k ** AList sig n k) flexRigid {n = S n} x t = case check x t of - Just u => Just (Evidence _ [<(u, x)]) + Just u => Just (_ ** [<(u, x)]) Nothing => Nothing export amgu : DecOp sig => - {n : Nat} -> + {k, n : Nat} -> (t, u : Term sig n) -> AList sig n k -> - Maybe (Exists (AList sig n)) + Maybe (k ** AList sig n k) amguAll : DecOp sig => - {n : Nat} -> + {k, n : Nat} -> (ts, us : Vect j (Term sig n)) -> AList sig n k -> - Maybe (Exists (AList sig n)) + Maybe (k ** AList sig n k) 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) [<] = Just (Evidence _ (flexFlex x y).snd) +amgu (Var x) (Var y) [<] = Just (flexFlex x y) 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)) = @@ -230,13 +230,13 @@ amgu t@(Var _) u@(Op _ _) (sub :< (v, z)) = 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 [] [] acc = Just (_ ** acc) amguAll (t :: ts) (u :: us) acc = do acc <- amgu t u acc amguAll ts us acc.snd export -mgu : DecOp sig => {n : Nat} -> (t, u : Term sig n) -> Maybe (Exists (AList sig n)) +mgu : DecOp sig => {n : Nat} -> (t, u : Term sig n) -> Maybe (k ** AList sig n k) mgu t u = amgu t u [<] -- Properties @@ -258,17 +258,17 @@ flexFlexUnifies {n = S n} x y with (thickProof x y) trivialUnify Var (Var x) flexFlexUnifies {n = S n} x _ | Thinned y prf = rewrite prf in - (Max (Unifies (Var x) (Var _))).cong _ _ + (UniqueMax (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 +data FlexRigidProof : Fin n -> Term sig n -> Maybe (k ** AList sig n k) -> Type where NoUnifier : Nothing (Unifies (Var x) t) -> res = Nothing -> FlexRigidProof x t res ElimVar : {n : Nat} -> (sub : AList sig k n) -> (mgu : MostGeneral (Unifies (Var x) t) (eval sub)) -> - res = Just (Evidence _ sub) -> + res = Just (_ ** sub) -> FlexRigidProof x t res flexRigidProof : @@ -301,7 +301,7 @@ flexRigidProof {n = S n} x op ts with (checkProof x (Op op ts)) rewrite prf in ElimVar [<(Op op us, x)] - ((Max (Unifies (Var x) (Op op _))).cong _ _ + ((UniqueMax (Unifies (Var x) (Op op _))).cong _ _ (\i => sym $ subUnit ((Op op us `for` x) i)) (varElim x (Op op us))) Refl @@ -322,7 +322,7 @@ parameters {auto _ : DecOp sig} Term sig k -> Term sig k -> AList sig k n -> - Maybe (Exists (AList sig k)) -> + Maybe (n ** AList sig k n) -> Type where Failure : @@ -334,7 +334,7 @@ parameters {auto _ : DecOp sig} {0 sub : AList sig k n} -> (sub' : AList sig n j) -> MostGeneral (Extension (Unifies t u) (eval sub)) (eval sub') -> - res = Just (Evidence _ (sub' ++ sub)) -> + res = Just (_ ** sub' ++ sub) -> AmguProof t u sub res public export @@ -342,7 +342,7 @@ parameters {auto _ : DecOp sig} Vect j (Term sig k) -> Vect j (Term sig k) -> AList sig k n -> - Maybe (Exists (AList sig k)) -> + Maybe (n ** AList sig k n) -> Type where FailureAll : @@ -354,7 +354,7 @@ parameters {auto _ : DecOp sig} {0 sub : AList sig k n} -> (sub' : AList sig n j) -> MostGeneral (Extension (UnifiesAll ts us) (eval sub)) (eval sub') -> - res = Just (Evidence _ (sub' ++ sub)) -> + res = Just (_ ** sub' ++ sub) -> AmguAllProof ts us sub res export @@ -378,8 +378,8 @@ 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)) <=> - Max (Extension (UnifiesAll ts us) (eval sub)) + UniqueMax (Extension (Unifies (Op op ts) (Op op us)) (eval sub)) <=> + UniqueMax (Extension (UnifiesAll ts us) (eval sub)) cong = maxCong $ extendCong (eval sub) $ unifiesOp op ts us in Success sub' @@ -397,7 +397,10 @@ amguProof (Var x) (Var y) [<] = Success (flexFlex x y).snd (flexFlexUnifies x y) - Refl + (cong Just $ ext _ (flexFlex x y)) + where + ext : (0 b : a -> Type) -> (v : (x : a ** b x)) -> v = (v.fst ** v.snd) + ext b (fst ** snd) = 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 @@ -413,8 +416,8 @@ amguProof (Op op ts) (Var y) [<] with (flexRigidProof y op ts) _ | ElimVar sub val prf = let cong : - Max (Extension (Unifies (Var y) (Op op ts)) Var) <=> - Max (Extension (Unifies (Op op ts) (Var y)) Var) + UniqueMax (Extension (Unifies (Var y) (Op op ts)) Var) <=> + UniqueMax (Extension (Unifies (Op op ts) (Var y)) Var) cong = maxCong $ extendCong Var $ unifiesSym (Var y) (Op op ts) in Success sub (cong.leftToRight _ val) prf @@ -423,8 +426,8 @@ amguProof (Var x) (Var y) (sub :< (v, z)) _ | Success sub' val prf = let cong' : - Max (Extension (Unifies (Var x) (Var y)) (eval sub . (v `for` z))) <=> - Max (Extension (Unifies ((v `for` z) x) ((v `for` z) y)) (eval sub)) + UniqueMax (Extension (Unifies (Var x) (Var y)) (eval sub . (v `for` z))) <=> + UniqueMax (Extension (Unifies ((v `for` z) x) ((v `for` z) y)) (eval sub)) cong' = maxCong $ stepEquiv (Var x) (Var y) sub v z in Success sub' @@ -439,8 +442,8 @@ amguProof (Var x) (Op op' us) (sub :< (v, z)) _ | Success sub' val prf = let cong' : - Max (Extension (Unifies (Var x) (Op op' us)) (eval sub . (v `for` z))) <=> - Max (Extension (Unifies ((v `for` z) x) ((v `for` z) <$> Op op' us)) (eval sub)) + UniqueMax (Extension (Unifies (Var x) (Op op' us)) (eval sub . (v `for` z))) <=> + UniqueMax (Extension (Unifies ((v `for` z) x) ((v `for` z) <$> Op op' us)) (eval sub)) cong' = maxCong $ stepEquiv (Var x) (Op op' us) sub v z in Success sub' @@ -455,8 +458,8 @@ amguProof (Op op ts) (Var y) (sub :< (v, z)) _ | Success sub' val prf = let cong' : - Max (Extension (Unifies (Op op ts) (Var y)) (eval sub . (v `for` z))) <=> - Max (Extension (Unifies ((v `for` z) <$> Op op ts) ((v `for` z) y)) (eval sub)) + UniqueMax (Extension (Unifies (Op op ts) (Var y)) (eval sub . (v `for` z))) <=> + UniqueMax (Extension (Unifies ((v `for` z) <$> Op op ts) ((v `for` z) y)) (eval sub)) cong' = maxCong $ stepEquiv (Op op ts) (Var y) sub v z in Success sub' @@ -470,7 +473,7 @@ amguProof (Op op ts) (Var y) (sub :< (v, z)) amguAllProof [] [] sub = SuccessAll [<] (varMostGeneral []) - (sym $ cong (\sub => Just (Evidence _ sub)) $ appendUnitLeft sub) + (sym $ cong (\sub => Just (_ ** sub)) $ appendUnitLeft sub) amguAllProof (t :: ts) (u :: us) sub with (amguProof t u sub) _ | Success sub' val prf with (amguAllProof ts us (sub' ++ sub)) _ | SuccessAll sub'' val' prf' = @@ -483,11 +486,11 @@ amguAllProof (t :: ts) (u :: us) sub with (amguProof t u sub) cong'.leftToRight (eval sub'') val' in SuccessAll (sub'' ++ sub') - ((Max (Extension (UnifiesAll (t :: ts) (u :: us)) (eval sub))).cong _ _ + ((UniqueMax (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)) $ + cong (\sub => Just (_ ** sub)) $ appendAssoc sub'' sub' sub) _ | FailureAll absurd prf' = let @@ -504,11 +507,12 @@ amguAllProof (t :: ts) (u :: us) sub with (amguProof t u sub) parameters {auto _ : DecOp sig} namespace MguProof public export - data MguProof : (t, u : Term sig k) -> Maybe (Exists (AList sig k)) -> Type where + data MguProof : (t, u : Term sig k) -> Maybe (n ** AList sig k n) -> Type where Success : + {n : Nat} -> (sub : AList sig k n) -> MostGeneral (Unifies t u) (eval sub) -> - res = Just (Evidence _ sub) -> + res = Just (_ ** sub) -> MguProof t u res Failure : Nothing (Unifies t u) -> @@ -520,3 +524,13 @@ mguProof : DecOp sig => {k : Nat} -> (t, u : Term sig k) -> MguProof t u (mgu t mguProof t u with (amguProof t u [<]) _ | Success sub val prf = Success sub val prf _ | Failure absurd prf = Failure absurd prf + +export +invertMgu : + DecOp sig => + {0 t, u : Term sig k} -> + MguProof t u res -> + res = Just (_ ** sub) -> + MostGeneral (Unifies t u) (eval sub) +invertMgu (Success sub mg Refl) Refl = mg +invertMgu (Failure _ prf) Refl = absurd prf |