module Data.CList (module Data.Peano, CList (..), fromList, uncons, head, tail, init, last, reverse) where import Prelude (Bool (..), Show (..), fst, snd, ($), (&&)) import Control.Applicative import Control.Category import Control.Monad import Data.Eq import Data.Foldable import Data.Functor.Classes import Data.Maybe import Data.Monoid hiding ((<>)) import Data.Natural.Class import Data.Ord import Data.Peano import Data.Semigroup import Data.Traversable import Data.Typeable import Text.Read (Read (..)) infixr 5 :. data CList n a where Nil :: CList Zero a (:.) :: a -> CList n a -> CList (Succ n) a deriving instance (Eq a) => Eq (CList n a) deriving instance (Ord a) => Ord (CList n a) deriving instance Functor (CList n) deriving instance Foldable (CList n) deriving instance Traversable (CList n) deriving instance Typeable CList instance Show a => Show (CList n a) where showsPrec = showsPrec1 instance (Read a, Natural n) => Read (CList n a) where readPrec = readPrec1 fromList :: Natural n => [a] -> Maybe (CList n a) fromList = t $ natural (T $ \ case [] -> Just Nil _ -> Nothing) (T $ \ case [] -> Nothing x:xs -> (x:.) <$> fromList xs) data T a n = T { t :: [a] -> Maybe (CList n a) } instance Semigroup a => Semigroup (CList n a) where Nil <> Nil = Nil (x:.xs) <> (y:.ys) = x<>y:.xs<>ys instance (Semigroup a, Monoid a) => Monoid (CList Zero a) where mempty = Nil mappend = (<>) instance (Semigroup a, Semigroup (CList n a), Monoid a, Monoid (CList n a)) => Monoid (CList (Succ n) a) where mempty = mempty:.mempty mappend = (<>) instance Applicative (CList Zero) where pure _ = Nil Nil <*> Nil = Nil instance (Applicative (CList n)) => Applicative (CList (Succ n)) where pure x = x :. pure x f:.fs <*> x:.xs = f x :. (fs <*> xs) instance Eq1 (CList n) where liftEq _ Nil Nil = True liftEq (==) (x:.xs) (y:.ys) = x == y && liftEq (==) xs ys instance Ord1 (CList n) where liftCompare _ Nil Nil = EQ liftCompare cmp (x:.xs) (y:.ys) = cmp x y <> liftCompare cmp xs ys instance Show1 (CList n) where liftShowsPrec sp sl n = liftShowsPrec sp sl n . toList instance Natural n => Read1 (CList n) where liftReadPrec rp rl = fromList <$> liftReadPrec rp rl >>= maybe empty pure uncons :: CList (Succ n) a -> (a, CList n a) uncons (x:.xs) = (x, xs) head :: CList (Succ n) a -> a head = fst . uncons tail :: CList (Succ n) a -> CList n a tail = snd . uncons init :: CList (Succ n) a -> CList n a init (_:.Nil) = Nil init (x:.xs@(_:._)) = x:.init xs last :: CList (Succ n) a -> a last (x:.Nil) = x last (_:.xs@(_:._)) = last xs reverse :: CList n a -> CList n a reverse Nil = Nil reverse xs@(_:._) = liftA2 (:.) last (reverse . init) xs