Functor / Applicative instances for State in Haskell

After reading (and skimming some sections of) Wadler's paper on monads, I decided to work through the paper more closely, defining functor and applicative instances for each of the monads he describes. Using the type synonym

type M a = State -> (a, State)
type State = Int

Wadler uses to define the state monad, I have the following (using related names so I can define them with a newtype declaration later on).

fmap' :: (a -> b) -> M a -> M b
fmap' f m = st -> let (a, s) = m st in (f a, s)

pure' :: a -> M a
pure' a = st -> (a, st)

(<@>) :: M (a -> b) -> M a -> M b
sf <@> sv = st -> let (f, st1) = sf st
                       (a, st2) = sv st1
                    in (f a, st2)

return' :: a -> M a
return' a = pure' a

bind :: M a -> (a -> M b) -> M b
m `bind` f = st -> let (a, st1) = m st
                        (b, st2) = f a st1
                     in (b, st2)

When I switch to using a type constructor in a newtype declaration, eg,

newtype S a = S (State -> (a, State))

everything falls apart. Everything is just a slight modification, for instance,

instance Functor S where
 fmap f (S m) = S (st -> let (a, s) = m st in (f a, s)) 

instance Applicative S where
 pure a = S (st -> (a, st))

however nothing runs in GHC due to the fact that the lambda expression is hidden inside that type constructor. Now the only solution I see is to define a function:

isntThisAnnoying s (S m) = m s

in order to bind s to 'st' and actually return a value, eg,

fmap f m = S (st -> let (a, s) = isntThisAnnoying st m in (f a, s))

Is there another way to do this that doesn't use these auxiliary functions?


If you look here, you will see that they define it this way:

newtype State s a = State { runState :: (s -> (a,s)) }

so as to give the inner lambda a name.


The usual way is to define newtype newtype S a = S {runState : State -> (a, State)} . Then instead of your isntThisAnnoying s (S m) you can write runState ts where t is the same as S m .
You have to use a newtype because type synonyms cannot be typeclass instances.

链接地址: http://www.djcxy.com/p/33216.html

上一篇: GHC可以为monad变压器派生Functor和Applicative实例吗?

下一篇: Funk / Applicative在Haskell中的状态实例