{-# LANGUAGE GADTs, ExistentialQuantification, EmptyDataDecls #-}
--- Slightly more complicated GADT example
--- Natural numbers and Length-indexed lists
module NList where
-- safe to export everything
-- natural numbers
data Z
data S x
data List n b where
Nil :: List Z a
Cons :: a -> List n a -> List (S n) a
instance Show b => Show (List n b) where
show Nil = "nil"
show (Cons x xs) = "(cons " ++ show x ++ " " ++ show xs ++ ")"
-- No definitions of nil/cons
sHead :: List (S n) b -> b
sHead (Cons x xs) = x
sTail :: List (S n) b -> List n b
sTail (Cons x xs) = xs
-- Bounded natural numbers. I.e. a number m that
-- is less than some other number n
data LT n where
Z :: LT (S n)
S :: LT n -> LT (S n)
coerce :: LT n -> LT (S n)
coerce Z = Z
coerce (S n) = S (coerce n)
{-
check :: Singlton n -> LT (S n) -> Maybe ( LT n )
check Z = Nothing
check (S Z) = Just (S Z)
-- n1 :: LT n
check (S n1@(S _)) = do m <- check n1
return (S m)
-}
toInt :: LT n -> Int
toInt Z = 0
toInt (S n) = 1 + toInt n
instance Show (LT n) where
show n = show (toInt n)
-- only lookup at a position less than the length of the list
cLookup :: LT n -> List m a -> Maybe a
cLookup Z (Cons x xs) = Just x
cLookup (S n) (Cons x xs) = cLookup n xs
cLookup _ Nil = Nothing
cLookup' :: LT n -> List m a -> Maybe (LT m)
cLookup' Z (Cons x xs) = Just Z
cLookup' (S n) (Cons x xs) = do n' <- (cLookup' n xs)
return (S n')
cLookup' _ Nil = Nothing
x :: List (S (S (S (S Z)))) Int
x = (Cons 1 (Cons 2 Nil))
y :: LT (S (S (S Z)))
y = (S (S Z))
sLookup :: LT n -> List n a -> a
sLookup Z (Cons x xs) = x
sLookup (S n) (Cons x xs) = sLookup n xs