diff options
author | Greg Brown <greg.brown01@ed.ac.uk> | 2024-10-28 15:34:16 +0000 |
---|---|---|
committer | Greg Brown <greg.brown01@ed.ac.uk> | 2024-10-28 15:34:16 +0000 |
commit | e258c78a5ab9529242b4c8fa168eda85430e641e (patch) | |
tree | 939ced9a71c94736222d05616a46dfc7292accd0 /src/Inky/Data | |
parent | d926ce9f2d1144f329598a30b3ed2e48899519b2 (diff) |
Make everything relevant.
Too few proofs were relevant. Now they are.
Diffstat (limited to 'src/Inky/Data')
-rw-r--r-- | src/Inky/Data/Assoc.idr | 26 | ||||
-rw-r--r-- | src/Inky/Data/Context.idr | 36 | ||||
-rw-r--r-- | src/Inky/Data/Context/Var.idr | 117 | ||||
-rw-r--r-- | src/Inky/Data/Fun.idr | 55 | ||||
-rw-r--r-- | src/Inky/Data/Irrelevant.idr | 19 | ||||
-rw-r--r-- | src/Inky/Data/Row.idr | 151 | ||||
-rw-r--r-- | src/Inky/Data/SnocList.idr | 43 | ||||
-rw-r--r-- | src/Inky/Data/SnocList/Elem.idr | 110 | ||||
-rw-r--r-- | src/Inky/Data/SnocList/Quantifiers.idr | 46 | ||||
-rw-r--r-- | src/Inky/Data/SnocList/Thinning.idr | 217 | ||||
-rw-r--r-- | src/Inky/Data/SnocList/Var.idr | 90 | ||||
-rw-r--r-- | src/Inky/Data/Thinned.idr | 18 |
12 files changed, 928 insertions, 0 deletions
diff --git a/src/Inky/Data/Assoc.idr b/src/Inky/Data/Assoc.idr new file mode 100644 index 0000000..a009515 --- /dev/null +++ b/src/Inky/Data/Assoc.idr @@ -0,0 +1,26 @@ +module Inky.Data.Assoc + +export +infix 2 :- + +public export +record Assoc (a : Type) where + constructor (:-) + name : String + value : a + +public export +Functor Assoc where + map f x = x.name :- f x.value + +namespace Irrelevant + public export + record Assoc0 (0 p : a -> Type) (x : Assoc a) where + constructor (:-) + 0 name : String + {auto 0 prf : x.name = name} + value : p x.value + + public export + map : (forall x. p x -> q x) -> forall x. Assoc0 p x -> Assoc0 q x + map f (n :- px) = n :- f px diff --git a/src/Inky/Data/Context.idr b/src/Inky/Data/Context.idr new file mode 100644 index 0000000..0d3df99 --- /dev/null +++ b/src/Inky/Data/Context.idr @@ -0,0 +1,36 @@ +module Inky.Data.Context + +import public Inky.Data.Assoc +import public Inky.Data.SnocList + +import Inky.Data.SnocList.Quantifiers + +-- Contexts -------------------------------------------------------------------- + +public export +Context : Type -> Type +Context a = SnocList (Assoc a) + +public export +(.names) : Context a -> SnocList String +[<].names = [<] +(ctx :< nx).names = ctx.names :< nx.name + +export +mapNames : (0 f : a -> b) -> (ctx : Context a) -> (map (map f) ctx).names = ctx.names +mapNames f [<] = Refl +mapNames f (ctx :< nx) = cong (:< nx.name) $ mapNames f ctx + +-- Construction ---------------------------------------------------------------- + +public export +fromAll : (ctx : Context a) -> All (const b) ctx.names -> Context b +fromAll [<] [<] = [<] +fromAll (ctx :< (n :- _)) (sx :< x) = fromAll ctx sx :< (n :- x) + +export +fromAllNames : + (ctx : Context a) -> (sx : All (const b) ctx.names) -> + (fromAll ctx sx).names = ctx.names +fromAllNames [<] [<] = Refl +fromAllNames (ctx :< (n :- _)) (sx :< x) = cong (:< n) $ fromAllNames ctx sx diff --git a/src/Inky/Data/Context/Var.idr b/src/Inky/Data/Context/Var.idr new file mode 100644 index 0000000..4741580 --- /dev/null +++ b/src/Inky/Data/Context/Var.idr @@ -0,0 +1,117 @@ +module Inky.Data.Context.Var + +import Data.DPair +import Data.Singleton +import Inky.Data.Context +import Inky.Data.SnocList.Elem +import Inky.Decidable +import Inky.Decidable.Maybe + +export +prefix 2 %%, %%% + +public export +record Var (ctx : Context a) (x : a) where + constructor (%%) + 0 name : String + {auto pos : Elem (name :- x) ctx} + +%name Var i, j, k + +public export +toVar : Elem (n :- x) ctx -> Var ctx x +toVar pos = (%%) n {pos} + +public export +ThereVar : Var ctx x -> Var (ctx :< ny) x +ThereVar i = toVar (There i.pos) + +export +Show (Var ctx x) where + show i = show (elemToNat i.pos) + +-- Basic Properties --------------------------------------------------------- + +export +toVarCong : + {0 n, k : String} -> {0 x, y : a} -> + {0 i : Elem (n :- x) ctx} -> {0 j : Elem (k :- y) ctx} -> + i ~=~ j -> toVar i ~=~ toVar j +toVarCong Refl = Refl + +export +posCong : {0 i : Var ctx x} -> {0 j : Var ctx y} -> i = j -> i.pos ~=~ j.pos +posCong Refl = Refl + +export +toVarInjective : + {0 n, k : String} -> {0 x, y : a} -> + {i : Elem (n :- x) ctx} -> {j : Elem (k :- y) ctx} -> + (0 _ : toVar i ~=~ toVar j) -> i ~=~ j +toVarInjective prf = toNatInjective $ toNatCong $ posCong prf + +export +posInjective : {i : Var ctx x} -> {j : Var ctx y} -> (0 _ : i.pos ~=~ j.pos) -> i ~=~ j +posInjective {i = %% x} {j = %% y} prf = irrelevantEq $ toVarCong prf + +-- Decidable Equality ---------------------------------------------------------- + +public export +decEq : (i : Var ctx x) -> (j : Var ctx y) -> Dec' (i ~=~ j) +decEq i j = + mapDec (\prf => irrelevantEq $ posInjective prf) posCong $ + decEq i.pos j.pos + +-- Weakening ------------------------------------------------------------------- + +public export +wknL : (len : LengthOf ctx2) => Var ctx1 x -> Var (ctx1 ++ ctx2) x +wknL i = toVar $ wknL i.pos len + +public export +wknR : Var ctx1 x -> Var (ctx2 ++ ctx1) x +wknR i = toVar $ wknR i.pos + +public export +split : {auto len : LengthOf ctx2} -> Var (ctx1 ++ ctx2) x -> Either (Var ctx1 x) (Var ctx2 x) +split i = bimap toVar toVar $ split len i.pos + +public export +lift : + {auto len : LengthOf ctx3} -> + (forall x. Var ctx1 x -> Var ctx2 x) -> + Var (ctx1 ++ ctx3) x -> Var (ctx2 ++ ctx3) x +lift f = either (wknL {len} . f) wknR . split {len} + +-- Names ----------------------------------------------------------------------- + +export +nameOf : {ctx : Context a} -> (i : Var ctx x) -> Singleton i.name +nameOf i = [| (nameOf i.pos).name |] + +-- Search ---------------------------------------------------------------------- + +export +lookup : (n : String) -> (ctx : Context a) -> Maybe (x ** Var ctx x) +lookup n ctx = + case decLookup n ctx of + Just x `Because` pos => Just (x ** toVar pos) + Nothing `Because` _ => Nothing + +namespace Search + public export + data VarPos : String -> a -> (ctx : Context a) -> Type where + [search ctx] + Here : VarPos n x (ctx :< (n :- x)) + There : VarPos n x ctx -> VarPos n x (ctx :< ky) + + %name VarPos pos + + public export + toElem : VarPos n x ctx -> Elem (n :- x) ctx + toElem Here = Here + toElem (There pos) = There (toElem pos) + + public export + (%%%) : (0 n : String) -> {auto pos : VarPos n x ctx} -> Var ctx x + (%%%) n {pos} = toVar $ toElem pos diff --git a/src/Inky/Data/Fun.idr b/src/Inky/Data/Fun.idr new file mode 100644 index 0000000..d9acb7d --- /dev/null +++ b/src/Inky/Data/Fun.idr @@ -0,0 +1,55 @@ +module Inky.Data.Fun + +import public Inky.Data.SnocList.Quantifiers +import Inky.Data.SnocList + +public export +Fun : SnocList Type -> Type -> Type +Fun [<] b = b +Fun (as :< a) b = Fun as (a -> b) + +public export +chain : (len : LengthOf as) -> (b -> c) -> Fun as b -> Fun as c +chain Z f x = f x +chain (S len) f g = chain len (f .) g + +public export +DFun : (as : SnocList Type) -> Fun as Type -> Type +DFun [<] p = p +DFun (as :< a) p = DFun as (chain (lengthOf as) (\f => (x : a) -> f x) p) + +public export +DIFun : (as : SnocList Type) -> Fun as Type -> Type +DIFun [<] p = p +DIFun (as :< a) p = DIFun as (chain (lengthOf as) (\f => {x : a} -> f x) p) + +public export +curry : (len : LengthOf as) -> (HSnocList as -> b) -> Fun as b +curry Z f = f [<] +curry (S len) f = curry len (f .: (:<)) + +public export +uncurry : Fun as b -> HSnocList as -> b +uncurry f [<] = f +uncurry f (sx :< x) = uncurry f sx x + +export +uncurryChain : + (0 g : b -> c) -> (0 f : Fun as b) -> (xs : HSnocList as) -> + uncurry (chain (lengthOf as) g f) xs = g (uncurry f xs) +uncurryChain g f [<] = Refl +uncurryChain g f (sx :< x) = cong (\f => f x) (uncurryChain (g .) f sx) + +export +dcurry : (len : LengthOf as) -> ((xs : HSnocList as) -> uncurry p xs) -> DFun as p +dcurry Z f = f [<] +dcurry (S len) f = + dcurry len (\sx => + replace {p = id} (sym $ uncurryChain (\f => (x : _) -> f x) p sx) + (\x => f (sx :< x))) + +export +duncurry : DFun as p -> (sx : HSnocList as) -> uncurry p sx +duncurry f [<] = f +duncurry f (sx :< x) = + replace {p = id} (uncurryChain (\f => (x : _) -> f x) p sx) (duncurry f sx) x diff --git a/src/Inky/Data/Irrelevant.idr b/src/Inky/Data/Irrelevant.idr new file mode 100644 index 0000000..ca72470 --- /dev/null +++ b/src/Inky/Data/Irrelevant.idr @@ -0,0 +1,19 @@ +module Inky.Data.Irrelevant + +public export +record Irrelevant (a : Type) where + constructor Forget + 0 value : a + +public export +Functor Irrelevant where + map f x = Forget (f x.value) + +public export +Applicative Irrelevant where + pure x = Forget x + f <*> x = Forget (f.value x.value) + +public export +Monad Irrelevant where + join x = Forget (x.value.value) diff --git a/src/Inky/Data/Row.idr b/src/Inky/Data/Row.idr new file mode 100644 index 0000000..ba0c5f6 --- /dev/null +++ b/src/Inky/Data/Row.idr @@ -0,0 +1,151 @@ +module Inky.Data.Row + +import public Data.So +import public Inky.Data.Context +import public Inky.Data.SnocList.Quantifiers + +import Inky.Data.SnocList.Elem +import Inky.Data.Irrelevant +import Inky.Decidable + +public export +FreshIn : String -> SnocList String -> Type +FreshIn n = All (\x => So (x /= n)) + +public export +AllFresh : SnocList String -> Type +AllFresh = Pairwise (So .: (/=)) + +public export +record Row (a : Type) where + constructor MkRow + context : Context a + 0 fresh : AllFresh context.names + +%name Row row + +public export +(.names) : Row a -> SnocList String +row.names = row.context.names + +-- Interfaces ------------------------------------------------------------------ + +public export +Functor Row where + map f row = MkRow (map (map f) row.context) (rewrite mapNames f row.context in row.fresh) + +public export +Foldable Row where + foldr f x row = foldr (\x, y => f x.value y) x row.context + foldl f x row = foldl (\x, y => f x y.value) x row.context + null row = null row.context + foldlM f x row = foldlM (\x, y => f x y.value) x row.context + foldMap f row = foldMap (f . value) row.context + +-- Equality -------------------------------------------------------------------- + +export +soUnique : (prf1, prf2 : So b) -> prf1 = prf2 +soUnique Oh Oh = Refl + +export +freshInUnique : (freshIn1, freshIn2 : x `FreshIn` sx) -> freshIn1 = freshIn2 +freshInUnique [<] [<] = Refl +freshInUnique (freshIn1 :< prf1) (freshIn2 :< prf2) = + cong2 (:<) (freshInUnique freshIn1 freshIn2) (soUnique prf1 prf2) + +export +freshUnique : (fresh1, fresh2 : AllFresh sx) -> fresh1 = fresh2 +freshUnique [<] [<] = Refl +freshUnique (fresh1 :< freshIn1) (fresh2 :< freshIn2) = + cong2 (:<) (freshUnique fresh1 fresh2) (freshInUnique freshIn1 freshIn2) + +export +rowCong : + {0 ctx1, ctx2 : Context a} -> + {0 fresh1 : AllFresh ctx1.names} -> + {0 fresh2 : AllFresh ctx2.names} -> + ctx1 = ctx2 -> MkRow ctx1 fresh1 = MkRow ctx2 fresh2 +rowCong Refl = rewrite freshUnique fresh1 fresh2 in Refl + +-- Smart Constructors ---------------------------------------------------------- + +public export +Lin : Row a +Lin = MkRow [<] [<] + +public export +(:<) : + (row : Row a) -> (x : Assoc a) -> + (0 fresh : x.name `FreshIn` row.names) => + Row a +row :< x = MkRow (row.context :< x) (row.fresh :< fresh) + +public export +fromAll : (row : Row a) -> All (const b) row.names -> Row b +fromAll row sx = MkRow (fromAll row.context sx) (rewrite fromAllNames row.context sx in row.fresh) + +-- Operations ------------------------------------------------------------------ + +export +isFresh : + (names : SnocList String) -> + (name : String) -> + Dec' (Irrelevant $ name `FreshIn` names) +isFresh names name = + map irrelevant (\contra, prfs => anyNegAll contra $ relevant names prfs.value) $ + all (\x => (decSo $ x /= name).forget) names + +export +extend : Row a -> Assoc a -> Maybe (Row a) +extend row x with (isFresh row.names x.name) + _ | True `Because` Forget prf = Just (row :< x) + _ | False `Because` _ = Nothing + +-- Search ---------------------------------------------------------------------- + +noLookupFresh : + (ctx : Context a) -> + (0 freshIn : n `FreshIn` ctx.names) -> + Not (Elem (n :- x) ctx) +noLookupFresh (sx :< (n :- x)) (freshIn :< prf) Here with ((decEq n n).reason) | ((decEq n n).does) + _ | _ | True = void $ absurd prf + _ | contra | False = void $ contra Refl +noLookupFresh (sx :< (k :- _)) (freshIn :< prf) (There i) = noLookupFresh sx freshIn i + +doLookupUnique : + (ctx : Context a) -> + (0 fresh : AllFresh ctx.names) -> + (i : Elem (n :- x) ctx) -> + (j : Elem (n :- y) ctx) -> + the (x ** Elem (n :- x) ctx) (x ** i) = (y ** j) +doLookupUnique (ctx :< (n :- x)) (fresh :< freshIn) Here Here = Refl +doLookupUnique (ctx :< (n :- x)) (fresh :< freshIn) Here (There j) = void $ noLookupFresh ctx freshIn j +doLookupUnique (ctx :< (n :- z)) (fresh :< freshIn) (There i) Here = void $ noLookupFresh ctx freshIn i +doLookupUnique (ctx :< (k :- z)) (fresh :< freshIn) (There i) (There j) = + cong (\(x ** i) => (x ** There i)) $ + doLookupUnique ctx fresh i j + +export +lookupUnique : + (row : Row a) -> + (i : Elem (n :- x) row.context) -> + (j : Elem (n :- y) row.context) -> + the (x ** Elem (n :- x) row.context) (x ** i) = (y ** j) +lookupUnique row i j = doLookupUnique row.context row.fresh i j + +-- Removal --------------------------------------------------------------------- + +dropElemFreshIn : + (ctx : Context a) -> n `FreshIn` ctx.names -> (i : Elem nx ctx) -> + n `FreshIn` (dropElem ctx i).names +dropElemFreshIn (ctx :< (n :- x)) (freshIn :< prf) Here = freshIn +dropElemFreshIn (ctx :< (n :- x)) (freshIn :< prf) (There i) = dropElemFreshIn ctx freshIn i :< prf + +export +dropElemFresh : + (ctx : Context a) -> AllFresh ctx.names -> (i : Elem nx ctx) -> + AllFresh (dropElem ctx i).names +dropElemFresh (ctx :< (n :- x)) (fresh :< freshIn) Here = fresh +dropElemFresh (ctx :< (n :- x)) (fresh :< freshIn) (There i) = + dropElemFresh ctx fresh i :< dropElemFreshIn ctx freshIn i diff --git a/src/Inky/Data/SnocList.idr b/src/Inky/Data/SnocList.idr new file mode 100644 index 0000000..494e8cc --- /dev/null +++ b/src/Inky/Data/SnocList.idr @@ -0,0 +1,43 @@ +module Inky.Data.SnocList + +import public Data.SnocList +import public Data.SnocList.Operations + +import Inky.Decidable.Maybe + +public export +data LengthOf : SnocList a -> Type where + Z : LengthOf [<] + S : LengthOf sx -> LengthOf (sx :< x) + +%name LengthOf len + +public export +lengthOfAppend : LengthOf sx -> LengthOf sy -> LengthOf (sx ++ sy) +lengthOfAppend len1 Z = len1 +lengthOfAppend len1 (S len2) = S (lengthOfAppend len1 len2) + +public export +lengthOf : (sx : SnocList a) -> LengthOf sx +lengthOf [<] = Z +lengthOf (sx :< x) = S (lengthOf sx) + +export +lengthUnique : (len1, len2 : LengthOf sx) -> len1 = len2 +lengthUnique Z Z = Refl +lengthUnique (S len1) (S len2) = cong S $ lengthUnique len1 len2 + +export +isSnoc : (sx : SnocList a) -> Proof (SnocList a, a) (\syy => sx = fst syy :< snd syy) (sx = [<]) +isSnoc [<] = Nothing `Because` Refl +isSnoc (sx :< x) = Just (sx, x) `Because` Refl + +public export +replicate : Nat -> a -> SnocList a +replicate 0 x = [<] +replicate (S n) x = replicate n x :< x + +public export +lengthOfReplicate : (n : Nat) -> (0 x : a) -> LengthOf (replicate n x) +lengthOfReplicate 0 x = Z +lengthOfReplicate (S k) x = S (lengthOfReplicate k x) diff --git a/src/Inky/Data/SnocList/Elem.idr b/src/Inky/Data/SnocList/Elem.idr new file mode 100644 index 0000000..465e92c --- /dev/null +++ b/src/Inky/Data/SnocList/Elem.idr @@ -0,0 +1,110 @@ +module Inky.Data.SnocList.Elem + +import public Data.SnocList.Elem + +import Data.DPair +import Data.Nat +import Data.Singleton +import Inky.Decidable +import Inky.Decidable.Maybe +import Inky.Data.Assoc +import Inky.Data.SnocList + +export +Uninhabited (Here {sx, x} ~=~ There {sx = sy, x = z, y} i) where + uninhabited Refl impossible + +export +Uninhabited (There {sx = sy, x = z, y} i ~=~ Here {sx, x}) where + uninhabited Refl impossible + +export +thereCong : + {0 i : Elem x sx} -> {0 j : Elem y sx} -> i = j -> + There {y = z} i = There {y = z} j +thereCong Refl = Refl + +export +toNatCong : {0 i : Elem x sx} -> {0 j : Elem y sx} -> i = j -> elemToNat i = elemToNat j +toNatCong Refl = Refl + +export +thereInjective : + {0 i : Elem x sx} -> {0 j : Elem y sx} -> There {y = z} i = There {y = z} j -> + i = j +thereInjective Refl = Refl + +export +toNatInjective : {i : Elem x sx} -> {j : Elem y sx} -> (0 _ : elemToNat i = elemToNat j) -> i = j +toNatInjective {i = Here} {j = Here} prf = Refl +toNatInjective {i = There i} {j = There j} prf with (toNatInjective {i} {j} $ injective prf) + toNatInjective {i = There i} {j = There .(i)} prf | Refl = Refl + +-- Decidable Equality ----------------------------------------------------------- + +public export +reflectEq : (i : Elem x sx) -> (j : Elem y sx) -> (i = j) `When` (elemToNat i == elemToNat j) +reflectEq Here Here = Refl +reflectEq Here (There j) = absurd +reflectEq (There i) Here = absurd +reflectEq (There i) (There j) = mapWhen thereCong thereInjective $ reflectEq i j + +public export +decEq : (i : Elem x sx) -> (j : Elem y sx) -> Dec' (i = j) +decEq i j = (elemToNat i == elemToNat j) `Because` reflectEq i j + +-- Weakening ------------------------------------------------------------------- + +public export +wknL : Elem x sx -> LengthOf sy -> Elem x (sx ++ sy) +wknL pos Z = pos +wknL pos (S len) = There (wknL pos len) + +public export +wknR : Elem x sx -> Elem x (sy ++ sx) +wknR Here = Here +wknR (There pos) = There (wknR pos) + +public export +split : LengthOf sy -> Elem x (sx ++ sy) -> Either (Elem x sx) (Elem x sy) +split Z pos = Left pos +split (S len) Here = Right Here +split (S len) (There pos) = mapSnd There $ split len pos + +-- Lookup ---------------------------------------------------------------------- + +export +nameOf : {sx : SnocList a} -> Elem x sx -> Singleton x +nameOf Here = Val x +nameOf (There pos) = nameOf pos + +-- Search ---------------------------------------------------------------------- + +export +lookup : DecEq' a => (x : a) -> (sx : SnocList a) -> Maybe (Elem x sx) +lookup x [<] = Nothing +lookup x (sx :< y) = + case decEq x y of + True `Because` Refl => Just Here + False `Because` _ => There <$> lookup x sx + +public export +decLookup : (n : String) -> (sx : SnocList (Assoc a)) -> DecWhen a (\x => Elem (n :- x) sx) +decLookup n [<] = Nothing `Because` (\_ => absurd) +decLookup n (sx :< (k :- x)) = + map (maybe x id) leftToRight rightToLeft $ + first (decEq n k) (decLookup n sx) + where + leftToRight : + forall n. (m : Maybe a) -> + maybe (n = k) (\y => Elem (n :- y) sx) m -> + Elem (n :- maybe x Basics.id m) (sx :< (k :- x)) + leftToRight Nothing Refl = Here + leftToRight (Just _) prf = There prf + + rightToLeft : + forall n. + (Not (n = k), (y : a) -> Not (Elem (n :- y) sx)) -> + (y : a) -> Not (Elem (n :- y) (sx :< (k :- x))) + rightToLeft (neq, contra) _ Here = neq Refl + rightToLeft (neq, contra) y (There i) = contra y i diff --git a/src/Inky/Data/SnocList/Quantifiers.idr b/src/Inky/Data/SnocList/Quantifiers.idr new file mode 100644 index 0000000..73c6551 --- /dev/null +++ b/src/Inky/Data/SnocList/Quantifiers.idr @@ -0,0 +1,46 @@ +module Inky.Data.SnocList.Quantifiers + +import public Data.SnocList.Quantifiers + +import Data.List.Quantifiers +import Inky.Data.Irrelevant +import Inky.Decidable + +public export +(<><) : All p xs -> All p sx -> All p (xs <>< sx) +sxp <>< [] = sxp +sxp <>< (px :: pxs) = (sxp :< px) <>< pxs + +public export +head : All p (sx :< x) -> p x +head (prfs :< px) = px + +public export +tail : All p (sx :< x) -> All p sx +tail (prfs :< px) = prfs + +public export +HSnocList : SnocList Type -> Type +HSnocList = All id + +public export +all : ((x : a) -> Dec' (p x)) -> (sx : SnocList a) -> LazyEither (All p sx) (Any (Not . p) sx) +all f [<] = True `Because` [<] +all f (sx :< x) = + map (\prfs => snd prfs :< fst prfs) (either Here There) $ + both (f x) (all f sx) + +public export +irrelevant : {0 sx : SnocList a} -> All (Irrelevant . p) sx -> Irrelevant (All p sx) +irrelevant [<] = Forget [<] +irrelevant (prfs :< px) = [| irrelevant prfs :< px |] + +public export +relevant : (sx : SnocList a) -> (0 prfs : All p sx) -> All (Irrelevant . p) sx +relevant [<] _ = [<] +relevant (sx :< x) prfs = relevant sx (tail prfs) :< Forget (head prfs) + +public export +data Pairwise : (a -> a -> Type) -> SnocList a -> Type where + Lin : Pairwise r [<] + (:<) : Pairwise r sx -> All (flip r x) sx -> Pairwise r (sx :< x) diff --git a/src/Inky/Data/SnocList/Thinning.idr b/src/Inky/Data/SnocList/Thinning.idr new file mode 100644 index 0000000..f766069 --- /dev/null +++ b/src/Inky/Data/SnocList/Thinning.idr @@ -0,0 +1,217 @@ +module Inky.Data.SnocList.Thinning + +import Data.DPair +import Data.Nat +import Inky.Data.SnocList +import Inky.Data.SnocList.Var +import Inky.Data.SnocList.Quantifiers +import Inky.Decidable.Maybe + +-------------------------------------------------------------------------------- +-- Thinnings ------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +public export +data Thins : SnocList a -> SnocList a -> Type where + Id : sx `Thins` sx + Drop : sx `Thins` sy -> sx `Thins` sy :< x + Keep : sx `Thins` sy -> sx :< x `Thins` sy :< x + +%name Thins f, g, h + +-- Basics + +public export +indexPos : (f : sx `Thins` sy) -> (pos : Elem x sx) -> Elem x sy +indexPos Id pos = pos +indexPos (Drop f) pos = There (indexPos f pos) +indexPos (Keep f) Here = Here +indexPos (Keep f) (There pos) = There (indexPos f pos) + +public export +index : (f : sx `Thins` sy) -> Var sx -> Var sy +index f i = toVar (indexPos f i.pos) + +public export +(.) : sy `Thins` sz -> sx `Thins` sy -> sx `Thins` sz +Id . g = g +Drop f . g = Drop (f . g) +Keep f . Id = Keep f +Keep f . Drop g = Drop (f . g) +Keep f . Keep g = Keep (f . g) + +-- Basic properties + +export +indexPosInjective : + (f : sx `Thins` sy) -> {i : Elem x sx} -> {j : Elem y sx} -> + (0 _ : elemToNat (indexPos f i) = elemToNat (indexPos f j)) -> i = j +indexPosInjective Id prf = toNatInjective prf +indexPosInjective (Drop f) prf = indexPosInjective f (injective prf) +indexPosInjective (Keep f) {i = Here} {j = Here} prf = Refl +indexPosInjective (Keep f) {i = There i} {j = There j} prf = + thereCong (indexPosInjective f $ injective prf) + +export +indexPosComp : + (f : sy `Thins` sz) -> (g : sx `Thins` sy) -> (pos : Elem x sx) -> + indexPos (f . g) pos = indexPos f (indexPos g pos) +indexPosComp Id g pos = Refl +indexPosComp (Drop f) g pos = cong There (indexPosComp f g pos) +indexPosComp (Keep f) Id pos = Refl +indexPosComp (Keep f) (Drop g) pos = cong There (indexPosComp f g pos) +indexPosComp (Keep f) (Keep g) Here = Refl +indexPosComp (Keep f) (Keep g) (There pos) = cong There (indexPosComp f g pos) + +-- Congruence ------------------------------------------------------------------ + +export +infix 6 ~~~ + +public export +data (~~~) : sx `Thins` sy -> sx `Thins` sz -> Type where + IdId : Id ~~~ Id + IdKeep : Id ~~~ f -> Id ~~~ Keep f + KeepId : f ~~~ Id -> Keep f ~~~ Id + DropDrop : f ~~~ g -> Drop f ~~~ Drop g + KeepKeep : f ~~~ g -> Keep f ~~~ Keep g + +%name Thinning.(~~~) prf + +export +(.indexPos) : f ~~~ g -> (pos : Elem x sx) -> elemToNat (indexPos f pos) = elemToNat (indexPos g pos) +(IdId).indexPos pos = Refl +(IdKeep prf).indexPos Here = Refl +(IdKeep prf).indexPos (There pos) = cong S $ prf.indexPos pos +(KeepId prf).indexPos Here = Refl +(KeepId prf).indexPos (There pos) = cong S $ prf.indexPos pos +(DropDrop prf).indexPos pos = cong S $ prf.indexPos pos +(KeepKeep prf).indexPos Here = Refl +(KeepKeep prf).indexPos (There pos) = cong S $ prf.indexPos pos + +export +(.index) : + {0 f, g : sx `Thins` sy} -> f ~~~ g -> (i : Var sx) -> index f i = index g i +prf.index ((%%) n {pos}) = irrelevantEq $ toVarCong $ toNatInjective $ prf.indexPos pos + +-- Useful for Parsers ---------------------------------------------------------- + +public export +dropPos : (pos : Elem x ctx) -> dropElem ctx pos `Thins` ctx +dropPos Here = Drop Id +dropPos (There pos) = Keep (dropPos pos) + +public export +dropAll : LengthOf sy -> sx `Thins` sx ++ sy +dropAll Z = Id +dropAll (S len) = Drop (dropAll len) + +public export +keepAll : LengthOf sz -> sx `Thins` sy -> sx ++ sz `Thins` sy ++ sz +keepAll Z f = f +keepAll (S len) f = Keep (keepAll len f) + +public export +append : + sx `Thins` sz -> sy `Thins` sw -> + {auto len : LengthOf sw} -> + sx ++ sy `Thins` sz ++ sw +append f Id = keepAll len f +append f (Drop g) {len = S len} = Drop (append f g) +append f (Keep g) {len = S len} = Keep (append f g) + +public export +assoc : LengthOf sz -> sx ++ (sy ++ sz) `Thins` (sx ++ sy) ++ sz +assoc Z = Id +assoc (S len) = Keep (assoc len) + +public export +growLengthOf : sx `Thins` sy -> LengthOf sx -> LengthOf sy +growLengthOf Id len = len +growLengthOf (Drop f) len = S (growLengthOf f len) +growLengthOf (Keep f) (S len) = S (growLengthOf f len) + +public export +thinLengthOf : sx `Thins` sy -> LengthOf sy -> LengthOf sx +thinLengthOf Id len = len +thinLengthOf (Drop f) (S len) = thinLengthOf f len +thinLengthOf (Keep f) (S len) = S (thinLengthOf f len) + +public export +thinAll : sx `Thins` sy -> All p sy -> All p sx +thinAll Id env = env +thinAll (Drop f) (env :< px) = thinAll f env +thinAll (Keep f) (env :< px) = thinAll f env :< px + +public export +splitL : + {0 sx, sy, sz : SnocList a} -> + LengthOf sz -> + sx `Thins` sy ++ sz -> + Exists (\sxA => Exists (\sxB => (sx = sxA ++ sxB, sxA `Thins` sy, sxB `Thins` sz))) +splitL Z f = Evidence sx (Evidence [<] (Refl, f, Id)) +splitL (S len) Id = Evidence sy (Evidence sz (Refl, Id, Id)) +splitL (S len) (Drop f) = + let Evidence sxA (Evidence sxB (Refl, g, h)) = splitL len f in + Evidence sxA (Evidence sxB (Refl, g, Drop h)) +splitL (S len) (Keep f) = + let Evidence sxA (Evidence sxB (Refl, g, h)) = splitL len f in + Evidence sxA (Evidence (sxB :< _) (Refl, g, Keep h)) + +public export +splitR : + {0 sx, sy, sz : SnocList a} -> + LengthOf sy -> + sx ++ sy `Thins` sz -> + Exists (\sxA => Exists (\sxB => (sz = sxA ++ sxB, sx `Thins` sxA, sy `Thins` sxB))) +splitR Z f = Evidence sz (Evidence [<] (Refl, f, Id)) +splitR (S len) Id = Evidence sx (Evidence sy (Refl, Id, Id)) +splitR (S len) (Drop f) = + let Evidence sxA (Evidence sxB (Refl, g, h)) = splitR (S len) f in + Evidence sxA (Evidence (sxB :< _) (Refl, g, Drop h)) +splitR (S len) (Keep f) = + let Evidence sxA (Evidence sxB (Refl, g, h)) = splitR len f in + Evidence sxA (Evidence (sxB :< _) (Refl, g, Keep h)) + +-- Strengthening --------------------------------------------------------------- + +public export +data Skips : sx `Thins` sy -> Elem y sy -> Type where + Here : Drop f `Skips` Here + Also : f `Skips` i -> Drop f `Skips` There i + There : f `Skips` i -> Keep f `Skips` There i + +%name Skips skips + +public export +strengthen : + (f : sx `Thins` sy) -> (i : Elem y sy) -> + Proof (Elem y sx) (\j => i = indexPos f j) (f `Skips` i) +strengthen Id i = Just i `Because` Refl +strengthen (Drop f) Here = Nothing `Because` Here +strengthen (Drop f) (There i) = + map id (\_, prf => cong There prf) Also $ + strengthen f i +strengthen (Keep f) Here = Just Here `Because` Refl +strengthen (Keep f) (There i) = + map There (\_, prf => cong There prf) There $ + strengthen f i + +export +skipsDropPos : (i : Elem x sx) -> dropPos i `Skips` j -> i ~=~ j +skipsDropPos Here Here = Refl +skipsDropPos (There i) (There skips) = thereCong (skipsDropPos i skips) + +------------------------ ------------------------------------------------------- +-- Renaming Coalgebras --------------------------------------------------------- +-------------------------------------------------------------------------------- + +public export +interface Rename (0 a : Type) (0 t : SnocList a -> Type) where + rename : + {0 sx, sy : SnocList a} -> sx `Thins` sy -> + t sx -> t sy + 0 renameCong : + {0 sx, sy : SnocList a} -> {0 f, g : sx `Thins` sy} -> f ~~~ g -> + (x : t sx) -> rename f x = rename g x + 0 renameId : {0 sx : SnocList a} -> (x : t sx) -> rename Id x = x diff --git a/src/Inky/Data/SnocList/Var.idr b/src/Inky/Data/SnocList/Var.idr new file mode 100644 index 0000000..cc7c088 --- /dev/null +++ b/src/Inky/Data/SnocList/Var.idr @@ -0,0 +1,90 @@ +module Inky.Data.SnocList.Var + +import public Inky.Data.SnocList.Elem + +import Data.Singleton +import Inky.Data.SnocList +import Inky.Decidable + +export +prefix 2 %% + +public export +record Var (sx : SnocList a) where + constructor (%%) + 0 name : a + {auto pos : Elem name sx} + +%name Var i, j, k + +public export +toVar : Elem x sx -> Var sx +toVar pos = (%%) x {pos} + +public export +ThereVar : Var sx -> Var (sx :< x) +ThereVar i = toVar (There i.pos) + +export +Show (Var sx) where + show i = show (elemToNat i.pos) + +-- Basic Properties --------------------------------------------------------- + +export +toVarCong : {0 i : Elem x sx} -> {0 j : Elem y sx} -> i = j -> toVar i = toVar j +toVarCong Refl = Refl + +export +posCong : {0 i, j : Var sx} -> i = j -> i.pos ~=~ j.pos +posCong Refl = Refl + +export +toVarInjective : {i : Elem x sx} -> {j : Elem y sx} -> (0 _ : toVar i = toVar j) -> i = j +toVarInjective prf = toNatInjective $ toNatCong $ posCong prf + +export +posInjective : {i : Var sx} -> {j : Var sx} -> (0 _ : i.pos ~=~ j.pos) -> i = j +posInjective {i = %% x} {j = %% y} prf = irrelevantEq $ toVarCong prf + +-- Decidable Equality ---------------------------------------------------------- + +public export +DecEq' (Var {a} sx) where + does i j = (decEq i.pos j.pos).does + reason i j = + mapWhen (\prf => irrelevantEq $ posInjective prf) posCong $ + (decEq i.pos j.pos).reason + +-- Weakening ------------------------------------------------------------------- + +public export +wknL : (len : LengthOf sy) => Var sx -> Var (sx ++ sy) +wknL i = toVar $ wknL i.pos len + +public export +wknR : Var sx -> Var (sy ++ sx) +wknR i = toVar $ wknR i.pos + +public export +split : {auto len : LengthOf sy} -> Var (sx ++ sy) -> Either (Var sx) (Var sy) +split i = bimap toVar toVar $ split len i.pos + +public export +lift1 : + (Var sx -> Var sy) -> + Var (sx :< x) -> Var (sy :< y) +lift1 f ((%%) x {pos = Here}) = %% y +lift1 f ((%%) name {pos = There i}) = ThereVar (f $ %% name) + +-- Names ----------------------------------------------------------------------- + +export +nameOf : {sx : SnocList a} -> (i : Var sx) -> Singleton i.name +nameOf i = nameOf i.pos + +-- Search ---------------------------------------------------------------------- + +export +lookup : DecEq' a => (x : a) -> (sx : SnocList a) -> Maybe (Var sx) +lookup x sx = toVar <$> lookup x sx diff --git a/src/Inky/Data/Thinned.idr b/src/Inky/Data/Thinned.idr new file mode 100644 index 0000000..6ee0d50 --- /dev/null +++ b/src/Inky/Data/Thinned.idr @@ -0,0 +1,18 @@ +module Inky.Data.Thinned + +import public Inky.Data.SnocList.Thinning + +public export +record Thinned (0 p : SnocList a -> Type) (ctx : SnocList a) where + constructor Over + {0 support : SnocList a} + value : p support + thins : support `Thins` ctx + +public export +rename : (ctx1 `Thins` ctx2) -> Thinned p ctx1 -> Thinned p ctx2 +rename f (value `Over` thins) = value `Over` (f . thins) + +public export +(.extract) : Rename a p => Thinned p ctx -> p ctx +(value `Over` thins).extract = rename thins value |