module Data.Term.Zipper import Data.DPair import Data.Fin.Occurs import Data.Vect.Properties.Insert import Data.Vect.Properties.Map import Data.Term import Syntax.PreorderReasoning -- Definition ------------------------------------------------------------------ public export data Zipper : Signature -> Nat -> Type where Top : Zipper sig n Op : sig.Operator (S k) -> Fin (S k) -> Vect k (Term sig n) -> Zipper sig n -> Zipper sig n %name Zipper zip -- Monoid ---------------------------------------------------------------------- export (++) : Zipper sig n -> Zipper sig n -> Zipper sig n Top ++ zip2 = zip2 Op op i ts zip1 ++ zip2 = Op op i ts (zip1 ++ zip2) -- Properties export leftUnit : (zip : Zipper sig n) -> Top ++ zip = zip leftUnit zip = Refl export rightUnit : (zip : Zipper sig n) -> zip ++ Top = zip rightUnit Top = Refl rightUnit (Op op i ts zip) = cong (Op op i ts) (rightUnit zip) export assoc : (zip1, zip2, zip3 : Zipper sig n) -> (zip1 ++ zip2) ++ zip3 = zip1 ++ (zip2 ++ zip3) assoc Top zip2 zip3 = Refl assoc (Op op i ts zip1) zip2 zip3 = cong (Op op i ts) (assoc zip1 zip2 zip3) -- Action ---------------------------------------------------------------------- export (+) : Zipper sig n -> Term sig n -> Term sig n Top + t = t Op op i ts zip + t = Op op (insertAt i (zip + t) ts) -- Properties export actionAssoc : (zip1, zip2 : Zipper sig n) -> (t : Term sig n) -> (zip1 ++ zip2) + t = zip1 + (zip2 + t) actionAssoc Top zip2 t = Refl actionAssoc (Op op i ts zip1) zip2 t = cong (\t => Op op (insertAt i t ts)) $ actionAssoc zip1 zip2 t -- Substitution ---------------------------------------------------------------- export (<$>) : (Fin k -> Term sig n) -> Zipper sig k -> Zipper sig n f <$> Top = Top f <$> Op op i ts zip = Op op i (map (f <$>) ts) (f <$> zip) -- Properties export actionHomo : (0 f : Fin k -> Term sig n) -> (zip : Zipper sig k) -> (0 t : Term sig k) -> f <$> zip + t = (f <$> zip) + (f <$> t) actionHomo f Top t = Refl actionHomo f (Op op i ts zip) t = cong (Op op) $ Calc $ |~ map (f <$>) (insertAt i (zip + t) ts) ~~ insertAt i (f <$> zip + t) (map (f <$>) ts) ...(mapInsertAt (f <$>) i (zip + t) ts) ~~ insertAt i ((f <$> zip) + (f <$> t)) (map (f <$>) ts) ...(cong (\t => insertAt i t (map (f <$>) ts)) $ actionHomo f zip t) -- Cycles ---------------------------------------------------------------------- pivotAt : sig.Operator k -> Fin k -> Vect k (Term sig n) -> Zipper sig n pivotAt op i ts = let op' = replace {p = sig.Operator} (snd prf) op in let i' = replace {p = Fin} (snd prf) i in let ts' = replace {p = flip Vect (Term sig n)} (snd prf) ts in Op op' i' (deleteAt i' ts') Top where prf : Exists (\j => k = S j) prf = indexIsSuc i actionPivotAt : (op : sig.Operator k) -> (i : Fin k) -> (ts : Vect k (Term sig n)) -> pivotAt op i ts + index i ts = Op op ts actionPivotAt op i@FZ ts = cong (Op op) $ insertAtIndex i ts actionPivotAt op i@(FS _) ts = cong (Op op) $ insertAtIndex i ts pivotNotTop : (zip : Zipper sig k) -> Not (zip ++ pivotAt op i ts = Top) pivotNotTop (Op op' j us zip) prf impossible export noCycles : (zip : Zipper sig k) -> (t : Term sig k) -> zip + t = t -> zip = Top noCycles Top t prf = Refl noCycles (Op {k} op i ts zip') t@(Op {k = j} op' us) prf = void $ pivotNotTop zip' prf'' where I : Fin j I = replace {p = Fin} (opInjectiveLen prf) i prf' : ((zip' ++ pivotAt op' I us) + index I us = index I us) prf' = Calc $ |~ (zip' ++ pivotAt op' I us) + index I us ~~ zip' + (pivotAt op' I us + index I us) ...(actionAssoc zip' (pivotAt op' I us) (index I us)) ~~ zip' + Op op' us ...(cong (zip' +) $ actionPivotAt op' I us) ~~ index i (insertAt i (zip' + Op op' us) ts) ..<(indexInsertAt i (zip' + Op op' us) ts) ~~ index i (rewrite opInjectiveLen prf in us) ...(cong (index i) $ opInjectiveTs prf) ~~ index I us ...(rewrite opInjectiveLen prf in Refl) prf'' : zip' ++ pivotAt op' I us = Top prf'' = noCycles (zip' ++ pivotAt op' I us) (assert_smaller t (index I us)) prf'