2021-09-09 17:56:10 -04:00
|
|
|
module Quox.Context
|
|
|
|
|
|
|
|
import Quox.Syntax.Shift
|
|
|
|
import Quox.Pretty
|
2022-04-23 18:21:30 -04:00
|
|
|
import public Quox.NatExtra
|
2021-09-09 17:56:10 -04:00
|
|
|
|
|
|
|
import Data.DPair
|
|
|
|
import Data.Nat
|
|
|
|
import Data.SnocList
|
|
|
|
import Control.Monad.Identity
|
|
|
|
|
|
|
|
%default total
|
|
|
|
|
|
|
|
|
|
|
|
infixl 5 :<
|
|
|
|
||| a sequence of bindings under an existing context. each successive element
|
|
|
|
||| has one more bound variable, which correspond to all previous elements
|
2022-08-22 04:17:08 -04:00
|
|
|
||| as well as the surrounding context.
|
2021-09-09 17:56:10 -04:00
|
|
|
public export
|
|
|
|
data Telescope : (tm : Nat -> Type) -> (from, to : Nat) -> Type where
|
|
|
|
Lin : Telescope tm from from
|
|
|
|
(:<) : Telescope tm from to -> tm to -> Telescope tm from (S to)
|
|
|
|
%name Telescope tel
|
|
|
|
|
2021-09-25 14:11:29 -04:00
|
|
|
public export
|
2021-12-23 09:54:16 -05:00
|
|
|
Telescope' : (a : Type) -> (from, to : Nat) -> Type
|
2021-09-25 14:11:29 -04:00
|
|
|
Telescope' a = Telescope (\_ => a)
|
|
|
|
|
2022-08-22 04:17:08 -04:00
|
|
|
||| a top level context is actually just a telescope over no existing bindings
|
2021-09-09 17:56:10 -04:00
|
|
|
public export
|
|
|
|
Context : (tm : Nat -> Type) -> (len : Nat) -> Type
|
|
|
|
Context tm len = Telescope tm 0 len
|
|
|
|
|
2021-09-25 14:11:29 -04:00
|
|
|
public export
|
2021-12-23 09:54:16 -05:00
|
|
|
Context' : (a : Type) -> (len : Nat) -> Type
|
2021-09-25 14:11:29 -04:00
|
|
|
Context' a = Context (\_ => a)
|
|
|
|
|
|
|
|
|
2022-04-23 18:21:30 -04:00
|
|
|
public export
|
|
|
|
tail : Context tm (S n) -> Context tm n
|
|
|
|
tail (tel :< _) = tel
|
|
|
|
|
2021-09-09 17:56:10 -04:00
|
|
|
export
|
2022-04-11 17:34:18 -04:00
|
|
|
toSnocList : Telescope tm _ _ -> SnocList (Exists tm)
|
2021-09-09 17:56:10 -04:00
|
|
|
toSnocList [<] = [<]
|
|
|
|
toSnocList (tel :< t) = toSnocList tel :< Evidence _ t
|
|
|
|
|
|
|
|
private
|
2022-04-11 17:34:18 -04:00
|
|
|
toListAcc : Telescope tm _ _ -> List (Exists tm) -> List (Exists tm)
|
2021-09-25 14:11:29 -04:00
|
|
|
toListAcc [<] acc = acc
|
|
|
|
toListAcc (tel :< t) acc = toListAcc tel (Evidence _ t :: acc)
|
2021-09-09 17:56:10 -04:00
|
|
|
|
|
|
|
export %inline
|
2022-04-11 17:34:18 -04:00
|
|
|
toList : Telescope tm _ _ -> List (Exists tm)
|
2021-09-25 14:11:29 -04:00
|
|
|
toList tel = toListAcc tel []
|
|
|
|
|
|
|
|
export %inline
|
2022-04-11 17:34:18 -04:00
|
|
|
toSnocList' : Telescope' a _ _ -> SnocList a
|
2021-09-25 14:11:29 -04:00
|
|
|
toSnocList' = map snd . toSnocList
|
|
|
|
|
|
|
|
export %inline
|
2022-04-11 17:34:18 -04:00
|
|
|
toList' : Telescope' a _ _ -> List a
|
2021-09-25 14:11:29 -04:00
|
|
|
toList' = map snd . toList
|
2021-09-09 17:56:10 -04:00
|
|
|
|
|
|
|
|
|
|
|
infixl 9 .
|
|
|
|
public export
|
|
|
|
(.) : Telescope tm from mid -> Telescope tm mid to -> Telescope tm from to
|
|
|
|
tel1 . [<] = tel1
|
|
|
|
tel1 . (tel2 :< s) = (tel1 . tel2) :< s
|
|
|
|
|
|
|
|
|
2021-12-23 09:55:18 -05:00
|
|
|
public export
|
2022-02-26 19:22:02 -05:00
|
|
|
getShiftWith : (forall from, to. tm from -> Shift from to -> tm to) ->
|
|
|
|
Shift len out -> Context tm len -> Var len -> tm out
|
2022-06-24 05:28:25 -04:00
|
|
|
getShiftWith shft by (ctx :< t) VZ = t `shft` ssDown by
|
|
|
|
getShiftWith shft by (ctx :< t) (VS i) = getShiftWith shft (ssDown by) ctx i
|
2022-02-26 19:22:02 -05:00
|
|
|
|
|
|
|
public export %inline
|
|
|
|
getShift : CanShift tm => Shift len out -> Context tm len -> Var len -> tm out
|
|
|
|
getShift = getShiftWith (//)
|
2021-09-09 17:56:10 -04:00
|
|
|
|
2021-12-23 09:55:18 -05:00
|
|
|
public export %inline
|
2022-02-26 19:22:02 -05:00
|
|
|
getWith : (forall from, to. tm from -> Shift from to -> tm to) ->
|
|
|
|
Context tm len -> Var len -> tm len
|
|
|
|
getWith shft = getShiftWith shft SZ
|
|
|
|
|
|
|
|
infixl 8 !!
|
2023-01-26 13:54:46 -05:00
|
|
|
public export %inline
|
2021-09-09 17:56:10 -04:00
|
|
|
(!!) : CanShift tm => Context tm len -> Var len -> tm len
|
2022-02-26 19:22:02 -05:00
|
|
|
(!!) = getWith (//)
|
2021-09-09 17:56:10 -04:00
|
|
|
|
2022-02-26 19:22:02 -05:00
|
|
|
infixl 8 !!!
|
2021-12-23 09:56:01 -05:00
|
|
|
public export %inline
|
2022-02-26 19:22:02 -05:00
|
|
|
(!!!) : Context' tm len -> Var len -> tm
|
|
|
|
(!!!) = getWith const
|
2021-12-23 09:56:01 -05:00
|
|
|
|
2021-09-09 17:56:10 -04:00
|
|
|
|
|
|
|
||| a triangle of bindings. each type binding in a context counts the ues of
|
|
|
|
||| others in its type, and all of these together form a triangle.
|
|
|
|
public export
|
|
|
|
Triangle : (tm : Nat -> Type) -> (len : Nat) -> Type
|
|
|
|
Triangle = Context . Context
|
|
|
|
|
2021-09-25 14:11:29 -04:00
|
|
|
public export
|
|
|
|
Triangle' : Type -> (len : Nat) -> Type
|
|
|
|
Triangle' a = Context $ Context (\_ => a)
|
2021-09-09 17:56:10 -04:00
|
|
|
|
|
|
|
export
|
|
|
|
0 telescopeLTE : Telescope _ from to -> from `LTE` to
|
2022-02-26 20:06:52 -05:00
|
|
|
telescopeLTE [<] = reflexive
|
2021-09-09 17:56:10 -04:00
|
|
|
telescopeLTE (tel :< _) = lteSuccRight $ telescopeLTE tel
|
|
|
|
|
|
|
|
export
|
2022-02-26 19:28:19 -05:00
|
|
|
(gt : from `GT` to) => Uninhabited (Telescope _ from to) where
|
|
|
|
uninhabited tel = void $ LTEImpliesNotGT (telescopeLTE tel) gt
|
2021-09-09 17:56:10 -04:00
|
|
|
|
|
|
|
export %hint
|
|
|
|
0 succGT : S n `GT` n
|
2022-02-26 20:06:52 -05:00
|
|
|
succGT = LTESucc reflexive
|
2021-09-09 17:56:10 -04:00
|
|
|
|
|
|
|
|
|
|
|
parameters {auto _ : Applicative f}
|
|
|
|
export
|
|
|
|
traverse : (forall n. tm1 n -> f (tm2 n)) ->
|
|
|
|
Telescope tm1 from to -> f (Telescope tm2 from to)
|
|
|
|
traverse f [<] = pure [<]
|
|
|
|
traverse f (tel :< x) = [|traverse f tel :< f x|]
|
|
|
|
|
|
|
|
infixl 3 `app`
|
|
|
|
||| like `(<*>)` but with effects
|
|
|
|
export
|
|
|
|
app : Telescope (\n => tm1 n -> f (tm2 n)) from to ->
|
|
|
|
Telescope tm1 from to -> f (Telescope tm2 from to)
|
|
|
|
app [<] [<] = pure [<]
|
|
|
|
app (ftel :< f) (xtel :< x) = [|app ftel xtel :< f x|]
|
2021-09-25 14:11:29 -04:00
|
|
|
app [<] (xtel :< _) = void $ uninhabited xtel
|
|
|
|
app (ftel :< _) [<] = void $ uninhabited ftel
|
2021-09-09 17:56:10 -04:00
|
|
|
|
|
|
|
export %inline
|
|
|
|
sequence : Telescope (f . tm) from to -> f (Telescope tm from to)
|
|
|
|
sequence = traverse id
|
|
|
|
|
2022-02-26 19:28:19 -05:00
|
|
|
parameters {0 tm1, tm2 : Nat -> Type}
|
|
|
|
(f : forall n. tm1 n -> tm2 n)
|
|
|
|
export %inline
|
|
|
|
map : Telescope tm1 from to -> Telescope tm2 from to
|
|
|
|
map = runIdentity . traverse (pure . f)
|
2021-09-09 17:56:10 -04:00
|
|
|
|
2022-02-26 19:28:19 -05:00
|
|
|
export %inline
|
|
|
|
(<$>) : Telescope tm1 from to -> Telescope tm2 from to
|
|
|
|
(<$>) = map
|
2021-09-09 17:56:10 -04:00
|
|
|
|
|
|
|
export %inline
|
|
|
|
(<*>) : Telescope (\n => tm1 n -> tm2 n) from to ->
|
|
|
|
Telescope tm1 from to -> Telescope tm2 from to
|
|
|
|
ftel <*> xtel = runIdentity $ (pure .) <$> ftel `app` xtel
|
2022-02-26 19:28:36 -05:00
|
|
|
-- ...but can't write pure without `from,to` being ω, so no idiom brackets ☹
|
|
|
|
|
2023-01-26 13:54:46 -05:00
|
|
|
export %inline
|
|
|
|
(<$) : (forall n. tm1 n) -> Telescope tm2 from to -> Telescope tm1 from to
|
|
|
|
x <$ tel = const x <$> tel
|
|
|
|
|
2022-04-11 17:33:32 -04:00
|
|
|
export
|
|
|
|
teleLte' : Telescope tm from to -> from `LTE'` to
|
|
|
|
teleLte' [<] = LTERefl
|
|
|
|
teleLte' (tel :< _) = LTESuccR (teleLte' tel)
|
2022-02-26 19:28:36 -05:00
|
|
|
|
|
|
|
|
2022-04-23 18:21:30 -04:00
|
|
|
export
|
|
|
|
tabulate : ((n : Nat) -> tm n) ->
|
|
|
|
(from, to : Nat) -> from `LTE'` to => Telescope tm from to
|
|
|
|
tabulate f from from @{LTERefl} = [<]
|
|
|
|
tabulate f from (S to) @{LTESuccR _} = tabulate f from to :< f to
|
|
|
|
|
|
|
|
export
|
|
|
|
tabulate0 : ((n : Nat) -> tm n) -> (n : Nat) -> Context tm n
|
|
|
|
tabulate0 f n = tabulate f 0 n
|
|
|
|
|
|
|
|
|
2022-02-26 19:28:36 -05:00
|
|
|
export
|
|
|
|
pure : from `LTE'` to => a -> Telescope' a from to
|
|
|
|
pure @{LTERefl} x = [<]
|
|
|
|
pure @{LTESuccR _} x = pure x :< x
|
2021-09-09 17:56:10 -04:00
|
|
|
|
2021-09-25 14:11:29 -04:00
|
|
|
|
2021-09-09 17:56:10 -04:00
|
|
|
export %inline
|
|
|
|
zipWith : (forall n. tm1 n -> tm2 n -> tm3 n) ->
|
|
|
|
Telescope tm1 from to -> Telescope tm2 from to ->
|
|
|
|
Telescope tm3 from to
|
|
|
|
zipWith f tel1 tel2 = f <$> tel1 <*> tel2
|
|
|
|
|
|
|
|
export %inline
|
|
|
|
zipWith3 : (forall n. tm1 n -> tm2 n -> tm3 n -> tm4 n) ->
|
|
|
|
Telescope tm1 from to ->
|
|
|
|
Telescope tm2 from to ->
|
|
|
|
Telescope tm3 from to ->
|
|
|
|
Telescope tm4 from to
|
|
|
|
zipWith3 f tel1 tel2 tel3 = f <$> tel1 <*> tel2 <*> tel3
|
|
|
|
|
2021-09-25 14:11:29 -04:00
|
|
|
export %inline
|
|
|
|
zipWithLazy : forall tm1, tm2, tm3.
|
|
|
|
(forall n. tm1 n -> tm2 n -> tm3 n) ->
|
|
|
|
Telescope tm1 from to -> Telescope tm2 from to ->
|
|
|
|
Telescope (\n => Lazy (tm3 n)) from to
|
|
|
|
zipWithLazy f = zipWith $ delay .: f
|
|
|
|
|
|
|
|
export %inline
|
|
|
|
zipWith3Lazy : forall tm1, tm2, tm3, tm4.
|
|
|
|
(forall n. tm1 n -> tm2 n -> tm3 n -> tm4 n) ->
|
|
|
|
Telescope tm1 from to ->
|
|
|
|
Telescope tm2 from to ->
|
|
|
|
Telescope tm3 from to ->
|
|
|
|
Telescope (\n => Lazy (tm4 n)) from to
|
2021-11-21 08:59:27 -05:00
|
|
|
zipWith3Lazy f = zipWith3 $ \x, y, z => delay $ f x y z
|
2021-09-25 14:11:29 -04:00
|
|
|
|
2021-09-09 17:56:10 -04:00
|
|
|
|
|
|
|
export
|
2022-04-11 17:34:28 -04:00
|
|
|
lengthPrf : Telescope _ from to -> Subset Nat (\len => len + from = to)
|
|
|
|
lengthPrf [<] = Element 0 Refl
|
2021-12-23 09:55:18 -05:00
|
|
|
lengthPrf (tel :< _) =
|
2022-04-11 17:34:28 -04:00
|
|
|
let len = lengthPrf tel in Element (S len.fst) (cong S len.snd)
|
2021-09-09 17:56:10 -04:00
|
|
|
|
2021-12-23 10:03:49 -05:00
|
|
|
export
|
2022-04-11 17:34:28 -04:00
|
|
|
lengthPrf0 : Context _ to -> Subset Nat (\len => len = to)
|
2021-12-23 10:03:49 -05:00
|
|
|
lengthPrf0 ctx =
|
2022-04-11 17:34:28 -04:00
|
|
|
let len = lengthPrf ctx in
|
|
|
|
Element len.fst (rewrite sym $ plusZeroRightNeutral len.fst in len.snd)
|
2021-12-23 10:03:49 -05:00
|
|
|
|
2021-09-09 17:56:10 -04:00
|
|
|
public export %inline
|
|
|
|
length : Telescope {} -> Nat
|
|
|
|
length = fst . lengthPrf
|
|
|
|
|
|
|
|
|
2021-12-23 09:55:18 -05:00
|
|
|
export
|
|
|
|
foldl : {0 acc : Nat -> Type} ->
|
|
|
|
(f : forall n. acc n -> tm (n + from) -> acc (S n)) ->
|
|
|
|
(z : acc 0) -> (tel : Telescope tm from to) -> acc (length tel)
|
|
|
|
foldl f z [<] = z
|
|
|
|
foldl f z (tel :< t) = f (foldl f z tel) (rewrite (lengthPrf tel).snd in t)
|
2021-09-09 17:56:10 -04:00
|
|
|
|
2021-12-23 09:55:18 -05:00
|
|
|
export %inline
|
|
|
|
foldMap : Monoid a => (forall n. tm n -> a) -> Telescope tm from to -> a
|
|
|
|
foldMap f = foldl (\acc, tm => acc <+> f tm) neutral
|
2021-09-09 17:56:10 -04:00
|
|
|
|
2021-12-23 09:55:18 -05:00
|
|
|
export %inline
|
|
|
|
fold : Monoid a => Telescope' a from to -> a
|
|
|
|
fold = foldMap id
|
2021-09-09 17:56:10 -04:00
|
|
|
|
2021-12-23 09:55:18 -05:00
|
|
|
||| like `fold` but calculate the elements only when actually appending
|
|
|
|
export %inline
|
|
|
|
foldLazy : Monoid a => Telescope' (Lazy a) from to -> a
|
|
|
|
foldLazy = foldMap force
|
2021-09-09 17:56:10 -04:00
|
|
|
|
|
|
|
|
2021-09-25 14:11:29 -04:00
|
|
|
export %inline
|
2021-11-21 08:59:27 -05:00
|
|
|
and : Telescope' (Lazy Bool) _ _ -> Bool
|
2021-09-25 14:11:29 -04:00
|
|
|
and = force . fold @{All}
|
|
|
|
|
|
|
|
export %inline
|
2021-11-21 08:59:27 -05:00
|
|
|
all : (forall n. tm n -> Bool) -> Telescope tm _ _ -> Bool
|
2021-09-25 14:11:29 -04:00
|
|
|
all p = and . map (delay . p)
|
|
|
|
|
|
|
|
export %inline
|
2021-11-21 08:59:27 -05:00
|
|
|
all2 : (forall n. tm n -> tm2 n -> Bool) ->
|
|
|
|
Telescope tm from to -> Telescope tm2 from to -> Bool
|
2021-09-25 14:11:29 -04:00
|
|
|
all2 p = and .: zipWithLazy p
|
|
|
|
|
|
|
|
|
|
|
|
export %inline
|
2021-11-21 08:59:27 -05:00
|
|
|
or : Telescope' (Lazy Bool) _ _ -> Bool
|
2021-09-25 14:11:29 -04:00
|
|
|
or = force . fold @{Any}
|
|
|
|
|
|
|
|
export %inline
|
2021-11-21 08:59:27 -05:00
|
|
|
any : (forall n. tm n -> Bool) -> Telescope tm _ _ -> Bool
|
2021-09-25 14:11:29 -04:00
|
|
|
any p = or . map (delay . p)
|
|
|
|
|
|
|
|
export %inline
|
2021-11-21 08:59:27 -05:00
|
|
|
any2 : (forall n. tm1 n -> tm2 n -> Bool) ->
|
|
|
|
Telescope tm1 from to -> Telescope tm2 from to -> Bool
|
2021-09-25 14:11:29 -04:00
|
|
|
any2 p = or .: zipWithLazy p
|
|
|
|
|
|
|
|
|
|
|
|
export %inline
|
2021-09-09 17:56:10 -04:00
|
|
|
(forall n. Eq (tm n)) => Eq (Telescope tm from to) where
|
2021-09-25 14:11:29 -04:00
|
|
|
(==) = all2 (==)
|
2021-09-09 17:56:10 -04:00
|
|
|
|
2021-09-25 14:11:29 -04:00
|
|
|
export %inline
|
2021-09-09 17:56:10 -04:00
|
|
|
(forall n. Ord (tm n)) => Ord (Telescope tm from to) where
|
2021-09-25 14:11:29 -04:00
|
|
|
compare = foldLazy .: zipWithLazy compare
|
2021-09-09 17:56:10 -04:00
|
|
|
|
2021-09-25 14:11:29 -04:00
|
|
|
export %inline
|
2021-09-09 17:56:10 -04:00
|
|
|
(forall n. PrettyHL (tm n)) => PrettyHL (Telescope tm from to) where
|
|
|
|
prettyM tel = separate (hl Delim ";") <$> traverse prettyM (toList tel)
|