free-functors-0.7: examples/NonEmptyList.hs
{-# LANGUAGE TemplateHaskell, TypeFamilies, DeriveFunctor, DeriveFoldable, DeriveTraversable, FlexibleInstances, UndecidableInstances #-}
module NonEmptyList where
import Data.Functor.Free
import Control.Comonad
import Data.Semigroup
-- A free semigroup allows you to create singletons and append them.
-- So it is a non-empty list.
type NonEmptyList = Free Semigroup
-- These instances make NonEmptyList a Semigroup and Show-able, Foldable and Traversable.
deriveInstances ''Semigroup
-- The next two instances make NonEmptyList a Comonad.
instance Semigroup (Extract a) where
a <> _ = a
instance Semigroup (Duplicate NonEmptyList a) where
Duplicate l <> Duplicate r = Duplicate $ ((<> extract r) <$> l) <> r
fromList :: [a] -> NonEmptyList a
fromList = foldr1 (<>) . map pure
-- Test the comonad and foldable instances, returns [10,9,7,4].
test :: NonEmptyList Int
test = extend sum $ (pure 1 <> pure 2) <> (pure 3 <> (pure 4 <> pure 5))