Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Applicative instance for free monad

While trying to find a haskell monad that can be executed stepwise / allows threading, I discovered the free monad

data Free f a = Return a | Roll (f (Free f a))

with its monad instance

instance (Functor f) => Monad (Free f) where
  return = Return
  Return x    >>= f = f x
  Roll action >>= f = Roll $ fmap (>>= f) action

and its functor instance

instance (Functor f) => Functor (Free f) where
  fmap f (Return x) = Return (f x)
  fmap f (Roll   x) = Roll $ fmap (fmap f) x

I know that every monad is an applicative functor with pure = return and (<*>) = ap. For me, applicative functors are conceptually harder than monads. For a better understanding of applicative functors, I like to have the applicative instance without resorting to ap.

The first line for <*>is easy:

instance (Applicative f) => Applicative (Free f) where
  pure = Return
  Return f <*> x = fmap f x -- follows immediately from pure f <*> x = f <$> x
--Roll   f <*> x = Roll $ (fmap ((fmap f) <*>)) x -- wrong, does not type-check

How to define Roll f <*> x in basic terms with fmap and <*>?

like image 712
Franky Avatar asked Mar 01 '14 23:03

Franky


People also ask

Are monads applicative?

Monads are not a replacement for applicative functors Instead, every monad is an applicative functor (as well as a functor). It is considered good practice not to use >>= if all you need is <*>, or even fmap.

What is the difference between functor and monad?

A functor takes a pure function (and a functorial value) whereas a monad takes a Kleisli arrow, i.e. a function that returns a monad (and a monadic value). Hence you can chain two monads and the second monad can depend on the result of the previous one.

What is applicative Haskell?

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. and can be thought of as bringing values into the applicative.

What is monad functor?

A functor is a data type that implements the Functor typeclass. An applicative is a data type that implements the Applicative typeclass. A monad is a data type that implements the Monad typeclass. A Maybe implements all three, so it is a functor, an applicative, and a monad.


1 Answers

Will this do?

instance (Functor f) => Applicative (Free f) where
  pure = Return
  Return f  <*> as  = fmap f as
  Roll faf  <*> as  = Roll (fmap (<*> as) faf)

The plan is to act only at the leaves of the tree which produces the function, so for Return, we act by applying the function to all the argument values produced by the argument action. For Roll, we just do to all the sub-actions what we intend to do to the overall action.

Crucially, what we do when we reach Return is already set before we start. We don't change our plans depending on where we are in the tree. That's the hallmark of being Applicative: the structure of the computation is fixed, so that values depend on values but actions don't.

like image 83
pigworker Avatar answered Oct 11 '22 11:10

pigworker