module SizedList
( SizedList(..)
, foldr
, foldrN
, toList
, length
, fromList
, unsafeFromList
, replicate
) where
import Prelude hiding ( foldr, replicate, length )
import Data.Maybe ( fromMaybe )
import TypeLevelNat ( Z(..), S(..), Nat, induction, witnessNat, N(..) )
data SizedList n a where
Nil :: SizedList Z a
(:::) :: a -> SizedList n a -> SizedList (S n) a
instance Functor (SizedList n) where
fmap _ Nil = Nil
fmap f (x ::: xs) = f x ::: fmap f xs
infixr 5 :::
consPrecedence :: Int
consPrecedence = 5
instance Show a => Show (SizedList n a) where
showsPrec _ Nil = showString "Nil"
showsPrec p (x ::: xs) = showParen (p > consPrecedence)
$ showsPrec (consPrecedence + 1) x
. showString " ::: "
. showsPrec consPrecedence xs
foldr :: forall a b n. (a -> b -> b) -> b -> SizedList n a -> b
foldr f z = foldr_f_z
where
foldr_f_z :: forall k. SizedList k a -> b
foldr_f_z Nil = z
foldr_f_z (x ::: xs) = f x $ foldr_f_z xs
foldrN :: forall a b n. (forall m. a -> b m -> b (S m)) -> b Z -> SizedList n a -> b n
foldrN f z = foldrN_f_z
where
foldrN_f_z :: forall k. SizedList k a -> b k
foldrN_f_z Nil = z
foldrN_f_z (x ::: xs) = f x $ foldrN_f_z xs
toList :: SizedList n a -> [a]
toList = foldr (:) []
length :: SizedList n a -> N n
length = foldrN (const Succ) Zero
newtype FromList a n = FL { unFL :: [a] -> Maybe (SizedList n a) }
fromList :: forall a n. Nat n => [a] -> Maybe (SizedList n a)
fromList = unFL $ induction (witnessNat :: n) (FL flZ) (FL . flS . unFL)
where
flZ [] = Just Nil
flZ _ = Nothing
flS _ [] = Nothing
flS k (x:xs) = fmap (x :::) $ k xs
unsafeFromList :: forall a n. Nat n => [a] -> SizedList n a
unsafeFromList = fromMaybe (error "unsafeFromList xs: xs does not have the right length ") .
fromList
newtype Replicate a n = R { unR :: SizedList n a}
replicate :: forall a n. Nat n => a -> SizedList n a
replicate x = unR $ induction (witnessNat :: n) (R Nil) (R . (x :::) . unR)