{-# LANGUAGE Safe #-}
module DeBruijn.Size (
Size (SZ, SS),
unSS,
sizeToInt,
pattern S1,
pattern S2,
pattern S3,
pattern S4,
pattern S5,
pattern S6,
pattern S7,
pattern S8,
pattern S9,
) where
import Data.EqP (EqP (..))
import Data.GADT.Compare (GCompare (..), GEq (..), GOrdering (..), defaultCompare, defaultEq)
import Data.GADT.Show (GShow (..))
import Data.Kind (Type)
import Data.OrdP (OrdP (..))
import Data.Type.Equality (TestEquality (testEquality), (:~:) (Refl))
import DeBruijn.Ctx
-- | Term level witness of the size of the context.
--
-- >>> SZ
-- 0
--
-- >>> SS (SS SZ)
-- 2
--
type Size :: Ctx -> Type
data Size ctx where
SZ :: Size EmptyCtx
SS :: !(Size ctx) -> Size (S ctx)
-------------------------------------------------------------------------------
-- Helpers
-------------------------------------------------------------------------------
unSS :: Size (S ctx) -> Size ctx
unSS (SS x) = x
sizeToInt :: Size ctx -> Int
sizeToInt = go 0 where
go :: Int -> Size ctx -> Int
go !n SZ = n
go n (SS s) = go (n + 1) s
-------------------------------------------------------------------------------
-- Instances
-------------------------------------------------------------------------------
instance Show (Size ctx) where
showsPrec d s = showsPrec d (sizeToInt s)
instance GShow Size where
gshowsPrec = showsPrec
instance Eq (Size ctx) where
_ == _ = True
instance Ord (Size ctx) where
compare _ _ = EQ
_ <= _ = True
_ >= _ = True
_ < _ = False
_ > _ = False
min x _ = x
max x _ = x
instance EqP Size where
eqp = defaultEq
instance OrdP Size where
comparep = defaultCompare
instance GEq Size where
geq SZ SZ = Just Refl
geq (SS n) (SS m) = do
Refl <- geq n m
Just Refl
geq _ _ = Nothing
instance GCompare Size where
gcompare SZ SZ = GEQ
gcompare SZ (SS _) = GLT
gcompare (SS _) SZ = GGT
gcompare (SS n) (SS m) = case gcompare n m of
GLT -> GLT
GEQ -> GEQ
GGT -> GGT
instance TestEquality Size where
testEquality = geq
-------------------------------------------------------------------------------
-- Sizes
-------------------------------------------------------------------------------
pattern S1 :: () => (m ~ Ctx1) => Size m
pattern S1 = SS SZ
pattern S2 :: () => (m ~ Ctx2) => Size m
pattern S2 = SS S1
pattern S3 :: () => (m ~ Ctx3) => Size m
pattern S3 = SS S2
pattern S4 :: () => (m ~ Ctx4) => Size m
pattern S4 = SS S3
pattern S5 :: () => (m ~ Ctx5) => Size m
pattern S5 = SS S4
pattern S6 :: () => (m ~ Ctx6) => Size m
pattern S6 = SS S5
pattern S7 :: () => (m ~ Ctx7) => Size m
pattern S7 = SS S6
pattern S8 :: () => (m ~ Ctx8) => Size m
pattern S8 = SS S7
pattern S9 :: () => (m ~ Ctx9) => Size m
pattern S9 = SS S8