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 vm
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
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 ms
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
.
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 sa)
.
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)
虽然,如前面的答案所述,这个实例一般不能定义,但值得注意的是,当f
是Applicative
且s
是Monoid
, StateT sf
也是Applicative
,因为它可以被认为是StateT sf
的组合。 :
StateT s f = Reader s `Compose` f `Compose` Writer s
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.