module GoodList ( GoodList(..) , singleton , cons , snoc , append ) where data GoodList a = Empty | Singleton a | Multiple a (GoodList a) a instance Functor GoodList where fmap _ Empty = Empty fmap f (Singleton a) = singleton $ f a fmap f (Multiple a b c) = Multiple (f a) (fmap f b) (f c) instance Applicative GoodList where pure = singleton Empty <*> _ = Empty (Singleton f) <*> x = fmap f x (Multiple a b c) <*> x = append (append (fmap a x) (b <*> x)) (fmap c x) instance Semigroup (GoodList a) where (<>) = append instance Monoid (GoodList a) where mempty = Empty instance Show a => Show (GoodList a) where show x = "[" ++ show' x ++ "]" where show' :: Show a => GoodList a -> String show' Empty = "" show' (Singleton a) = show a show' (Multiple a Empty c) = show a ++ ", " ++ show c show' (Multiple a b c) = show a ++ ", " ++ show' b ++ ", " ++ show c singleton :: a -> GoodList a singleton = Singleton cons :: a -> GoodList a -> GoodList a cons x Empty = singleton x cons x (Singleton a) = Multiple x Empty a cons x (Multiple a b c) = Multiple x (a `cons` b) c snoc :: GoodList a -> a -> GoodList a snoc Empty = singleton snoc (Singleton a) = Multiple a Empty snoc (Multiple a b c) = Multiple a (b `snoc` c) append :: GoodList a -> GoodList a -> GoodList a append Empty ys = ys append (Singleton x) ys = cons x ys append xs Empty = xs append (Multiple a b c) (Singleton y) = Multiple a (snoc b c) y append (Multiple a b c) (Multiple d e f) = Multiple a (snoc b c `append` cons d e) f