{-# LANGUAGE StandaloneDeriving #-} module Data.CList (module Data.Peano, CList (..), uncons, head, tail, init, last, reverse) where import Prelude (Read, Show, fst, snd) import Control.Applicative import Control.Category.Unicode import Data.Eq import Data.Foldable import Data.Functor import Data.Monoid import Data.Ord import Data.Peano import Data.Traversable import Data.Typeable 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 (Show a) => Show (CList n a) deriving instance Functor (CList n) deriving instance Foldable (CList n) deriving instance Traversable (CList n) deriving instance Typeable CList instance Monoid a => Monoid (CList Zero a) where mempty = Nil Nil `mappend` Nil = Nil instance (Monoid a, Monoid (CList n a)) => Monoid (CList (Succ n) a) where mempty = mempty:.mempty (x:.xs) `mappend` (y:.ys) = x<>y:.xs<>ys instance Applicative (CList Zero) where pure x = 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) 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 (x:.Nil) = Nil init (x:.xs@(_:._)) = x:.init xs last :: CList (Succ n) a -> a last (x:.Nil) = x last (x:.xs@(_:._)) = last xs reverse :: CList n a -> CList n a reverse Nil = Nil reverse xs@(_:._) = liftA2 (:.) last (reverse ∘ init) xs