Question

I'm currently working on Data.Fresh and Control.Monad.Trans.Fresh, which resp. define an interface for generating fresh variables, and a monad transformer which implements this interface.

I initially thought it would be possible to implement the Applicative instance for my FreshT v m with the only requirement that Applicative m exists. However, I got stuck and it seemed like I need to require Monad m. Not trusting my Haskell-fu, I then turned to the transformers package, and was surprised by what I found in Control.Monad.Trans.State.Lazy and .Strict:

instance (Functor m, Monad m) => Applicative (StateT s m) where
    pure = return
    (<*>) = ap

So here is my question: is it possible to create an instance with equivalent semantics with the following instance head?

instance (Applicative m) => Applicative (StateT s m) where
Was it helpful?

Solution

Consider that you have two functions:

 f :: s -> m (s, a -> b)
 g :: s -> m (s, a)

And you want to create a function h = StateT f <*> StateF g

 h :: s -> m (s, b)

From the above you have an s you can pass to f so you have:

 f' :: m (s, a -> b)
 g :: s -> m (s, a)

However to get s out of f' you need the Monad (whatever you'd do with applicative it would still be in form of m s so you would not be able to apply the value to g).

You can play with the definitions and use free monad but for the collapse of state you need join.

OTHER TIPS

Weaker variant of an Applicative transformer

Although it isn't possible to define an applicative transformer for StateT, It's possible to define a weaker variant that works. Instead of having s -> m (a, s), where the state decides the next effect (therefore m must be a monad), we can use m (s -> (a, s)), or equivalently m (State s a).

import Control.Applicative
import Control.Monad
import Control.Monad.State
import Control.Monad.Trans

newtype StateTA s m a = StateTA (m (State s a))

This is strictly weaker than StateT. Every StateTA can be made into StateT (but not vice versa):

toStateTA :: Applicative m => StateTA s m a -> StateT s m a
toStateTA (StateTA k) = StateT $ \s -> flip runState s <$> k

Defining Functor and Applicative is just the matter of lifting operations of State into the underlying m:

instance (Functor m) => Functor (StateTA s m) where
    fmap f (StateTA k) = StateTA $ liftM f <$> k
instance (Applicative m) => Applicative (StateTA s m) where
    pure = StateTA . pure . return
    (StateTA f) <*> (StateTA k) = StateTA $ ap <$> f <*> k    

And we can define an applicative variant of lift:

lift :: (Applicative m) => m a -> StateTA s m a
lift = StateTA . fmap return

Update: Actually the above isn't necessary, as the composition of two applicative functors is always an applicative functor (unlike monads). Our StateTA is isomorphic to Compose m (State s), which is automatically Applicative:

instance (Applicative f, Applicative g) => Applicative (Compose f g) where
    pure x = Compose (pure (pure x))
    Compose f <*> Compose x = Compose ((<*>) <$> f <*> x)

Therefore we could write just

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import Control.Applicative
import Control.Monad.State
import Data.Functor.Compose

newtype StateTA s m a = StateTA (Compose m (State s) a)
    deriving (Functor, Applicative)

Although, as noted in the previous answer, this instance cannot be defined in general, it is worth noting that, when f is Applicative and s is a Monoid, StateT s f is also Applicative, since it can be regarded as a composition of applicative functors:

StateT s f = Reader s `Compose` f `Compose` Writer s
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top