Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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, e.g.,

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, e.g.,

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?

like image 376
emi Avatar asked Aug 20 '10 18:08

emi


People also ask

What is functor in Haskell?

Functor in Haskell is a kind of functional representation of different Types which can be mapped over. It is a high level concept of implementing polymorphism. According to Haskell developers, all the Types such as List, Map, Tree, etc. are the instance of the Haskell Functor.

What is applicative in Haskell?

Definition. In Haskell, an applicative is a parametrized type that we think of as being a container for data of that type plus two methods pure and <*> . Consider a parametrized type f a . The pure method for an applicative of type f has type. pure :: a -> f a.

Is functor a Typeclass?

Functor in Haskell is a typeclass that provides two methods – fmap and (<$) – for structure-preserving transformations. To implement a Functor instance for a data type, you need to provide a type-specific implementation of fmap – the function we already covered.

Is Fmap a functor?

The expression fmap (*2) is a function that takes a functor f over numbers and returns a functor over numbers. That functor can be a list, a Maybe , an Either String, whatever. The expression fmap (replicate 3) will take a functor over any type and return a functor over a list of elements of that type.


2 Answers

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 t s where t is the same as S m.
You have to use a newtype because type synonyms cannot be typeclass instances.

like image 58
Daniel Avatar answered Sep 18 '22 14:09

Daniel


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.

like image 22
Daniel Pratt Avatar answered Sep 21 '22 14:09

Daniel Pratt