As Dan Doel points out here, the gadget Free that turns a functor into a monad is itself a kind of monad, though not the usual kind of monad we find in Haskell. I'll call it a higher order monad and you can find a type class corresponding to this in various places including an old version of Ed Kmett's category-extras. I'll borrow some code from there. I hunted around and couldn't find an implementation of Free as an instance of this class so I thought I'd plug the gap.





> {-# LANGUAGE RankNTypes, FlexibleContexts, InstanceSigs, ScopedTypeVariables #-}

> import Control.Monad > import Data.Monoid



To make things unambiguous I'll implement free monads in the usual way here:





> data Free f a = Pure a | Free (f (Free f a))

> instance Functor f => Functor (Free f) where > fmap f (Pure a) = Pure (f a) > fmap f (Free a) = Free (fmap (fmap f) a)

> instance Functor f => Monad (Free f) where > return = Pure > Pure a >>= f = f a > Free a >>= f = Free (fmap (>>= f) a)



Monad

Hask

Hask

Endo

The usual Haskell typeclasscorresponds to monads in the category of types and functions,. We're going to want monads in the category of endomorphisms ofwhich I'll call



The objects in Endo correspond to Haskell's Functor . The arrows in Endo are the natural transformations between these functors:





> type Natural f g = (Functor f, Functor g) => forall a. f a -> g a



Endo

So now we are led to consider functors in





> class HFunctor f where



Endo

Hask

Hask

f

Endo

g

Hask

f g

Hask

fmap

fmap

g

A functor inmust map functors into functors in. So ifis a functor inandis a functor in, thenmust be another functor in. So there must be anassociated with this new functor. There's an associatedfor everyand we collect them all into one big happy natural family:





> ffmap :: Functor g => (a -> b) -> f g a -> f g b



f

fmap

Endo

Hask

fmap

HFunctor

Endo

Endo

But note also that by virtue of being a functor itself,must have its owntype function associated with it. The arrows inare natural transformations inso theformust take arrows into arrows inlike so:





> hfmap :: (Functor g, Functor h) => Natural g h -> Natural (f g) (f h)



Hask

Endo

Hask

a

b

(a, b)

Endo

f

g

Many constructions in the categorycarry over to. Inwe can form a product of type typesandas. Inwe form the product of two functorsandas





> data Product f g a = Product (f (g a))



Product f g

Product g f

Hask

Endo

Product

Note that this product isn't commutative. We don't necessarily have an isomorphism fromto. (This breaks many attempts to transfer constructions fromto.) We also won't explicitly usebecause we can simply use the usual Haskell composition of functors inline.



We can implement some functions that act on product types in both senses of the word "product":





> left :: (a -> c) -> (a, b) -> (c, b) > left f (a, b) = (f a, b)

> right :: (b -> c) -> (a, b) -> (a, c) > right f (a, b) = (a, f b)

> hleft :: (Functor a, Functor b, Functor c) => Natural a c -> a (b x) -> c (b x) > hleft f = f

> hright :: (Functor a, Functor b, Functor c) => Natural b c -> a (b x) -> a (c x) > hright f = fmap f



(Compare with what I wrote here .)



We have something in Endo a bit like the type with one element in Hask , namely the identity functor. The product of a type a with the one element type in Hask gives you something isomorphic to a . In Endo the product is composition for which the identity functor is the identity. (Two different meanings of the word "identity" there.)



We also have sums. For example, if we define a functor like so





> data F a = A a | B a a



F

A

B

we can think ofas a sum of two functors: one with a single constructorand another with constructor



We can now think about reproducing an Endo flavoured version of lists. The usual definition is isomorphic to:





> data List a = Nil | Cons a (List a)



Monoid

And it has ainstance:





> instance Monoid (List a) where > mempty = Nil > mappend Nil as = as > mappend (Cons a as) bs = Cons a (mappend as bs)



Endo

Nil

Cons a (List a)

a

List a

We can try to translate that into. Thepart can be thought of as being an element of a type with one element so it should become the identity functor. Thepart is a product ofandso that should get replaced by a composition. So we expect to see something vaguely like:





List' a = Nil' | Cons' (a (List' a))



List' a

That's not quite right becauseis a functor, not a type, and so acts on types. So a better definition would be:





List' a b = Nil' b | Cons' (a (List' a b))



Free

Endo

That's just the definition of. So free monads are lists in. As everyone knows :-) monads are just monoids in the category of endofunctors. Free monads are also just free monoids in the category of endofunctors.



So now we can expect many constructions associated with monoids and lists to carry over to monads and free monads.



An obvious one is the generalization of the singleton map a -> List a :





> singleton :: a -> List a > singleton a = Cons a Nil

> hsingleton :: Natural f (Free f) > hsingleton f = Free (fmap Pure f)



foldMap

Another is the generalization of. This can be found under a variety of names in the various free monad libraries out there but this implementation is designed to highlight the similarity between monoids and monads:





> foldMap :: Monoid m => (a -> m) -> List a -> m > foldMap _ Nil = mempty > foldMap f (Cons a as) = uncurry mappend $ left f $ right (foldMap f) (a, as)

> fold :: Monoid m => List m -> m > fold = foldMap id

> hFoldMap :: (Functor f, Functor m, Monad m) => Natural f m -> Natural (Free f) m > hFoldMap _ (Pure x) = return x > hFoldMap f (Free x) = join $ hleft f $ hright (hFoldMap f) x

> hFold :: Monad f => Natural (Free f) f > hFold = hFoldMap id



foldMap

hFoldMap

The similarity here isn't simply formal. If you think of a list as a sequence of instructions theninterprets the sequence of instructions like a computer program. Similarlycan be used to interpret programs for which the free monad provides an abstract syntax tree.



You'll find some of these functions here by different names.



Now we can consider Free . It's easy to show this is a HFunctor by copying a suitable definition for List :





> instance Functor List where > fmap f = foldMap (singleton . f)

> instance HFunctor Free where > ffmap = fmap > hfmap f = hFoldMap (hsingleton . f)



HMonad

We can defineas follows:





> class HMonad m where > hreturn :: Functor f => f a -> m f a > hbind :: (Functor f, Functor g) => m f a -> Natural f (m g) -> m g a



Free

List

Monad

Before makingan instance, let's look at how we'd makean instance of





> instance Monad List where > return = singleton > m >>= f = fold (fmap f m)



And now the instance I promised at the beginning.





> instance HMonad Free where > hreturn = hsingleton > hbind m f = hFold (hfmap f m)



hreturn

hbind

Endo

I've skipped the proofs that the monad laws hold and thatandare actually natural transformations in. Maybe I'll leave those as exercises for the reader.



Update

After writing this I tried googling for "instance HMonad Free" and I found this by haasn. There's some other good stuff in there too.