Monad

Applicative

State s

State s

fmap

fmap

g a

fmap

data Lan g a where Lan :: g x -> (x -> a) -> Lan g a instance Functor (Lan g) where fmap f (Lan gx h) = Lan gx (f . h) lan :: g a -> Lan g a lan ga = Lan ga id

Lan

Lan g a

fmap

Functor

fmap

Free (Lan g)

g a

Free (Lan g)

data FFree g a where FPure :: a -> FFree g a FImpure :: g x -> (x -> FFree g a) -> FFree g a

Free f

g :: * -> *

FFree g

FFree g

instance Functor (FFree g) where fmap f (FPure x) = FPure (f x) fmap f (FImpure u q) = FImpure u (fmap f . q) instance Applicative (FFree g) where pure = FPure FPure f <*> x = fmap f x FImpure u q <*> x = FImpure u ((<*> x) . q) instance Monad (FFree g) where return = FPure FPure x >>= k = k x FImpure u k' >>= k = FImpure u (k' >>> k)

(>>>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c) f >>> g = (>>= g) . f

FFree g = Free (Lan f)

g a

etaF :: g a -> FFree g a etaF fa = FImpure fa FPure

eta

etaF

Functor

fmap

To make our State s a monad, we no longer have to write any instances at all, not even a Functor . We only have to say:

type FFState s = FFree (State s)

getFF :: FFState s s getFF = etaF get putFF :: s -> FFState s () putFF = etaF . put

runFFState :: FFState s a -> s -> (a,s) runFFState (FPure x) s = (x,s) runFFState (FImpure m q) s = let (x,s') = unState m s in runFFState (q x) s'

testState

The ``formal cheating'', the shifting of the work from the monad bind to the interpreter runFFState has become clearer. A typical computation, for example, testState , without syntax sugar looks like

((FImpure (put 10) Pure) >>= \_ -> getF) >>= \x -> return x

(((FImpure eff k1) >>= k2) >>= ...) >>= kn

eff

k1

kn

FFree g

FImpure eff (k1 >>> k2 >>> ... >>> kn)

runFFState

eff

FFree g

k1

kn

(>>>)

k1 >>> k2 >>> ... >>> kn

k1 >>> k2 >>> ... >>> kn