[Haskell-cafe] AMP - how do you motivate this in teaching?

Albert Y. C. Lai trebla at vex.net
Fri Nov 20 21:41:08 UTC 2015

On 2015-11-19 04:27 PM, Johannes Waldmann wrote:
> Now, I don't want to bring on another general discussion of AMP -
> instead I'd like to hear from people who use monads
> in teaching (e.g., to define semantic domains)
> about how they sell "Applicative m =>"  to their students.
> (The intersection of AMPers and teachers is non-empty?)

(I do not teach Haskell. But I teach other things, and I explain Haskell 
things in local Haskell meetups.)

I'm pretty sure we can all agree to start with Functor. This gives us 
fmap so we can apply a 1-ary function to 1 action.

But we are greedy, we also want to apply a 2-ary function to 2 actions. 
Functor alone can't do this. We need at least liftA2. And then we wonder 
about 3-ary, 4-ary...

It turns out that pure and (<*>) cover them all. To apply a 5-ary 
function to 5 actions, we can write the very regular

pure f <*> as <*> bs <*> cs <*> ds <*> es

(Given lambda calculus and Functor, the following suites have equivalent 
ability, so each suite could define Applicative: {pure, liftA2}, {pure, 
liftA2 (,)}, {pure, (<*>)}.)

It also turns out that you can already write sequenceA (you didn't use 
all of Monad to get sequence) and traverse (you didn't use all of Monad 
to get mapM).

So this is how I would motivate Applicative given Functor. I received 
the gift of 1-ary application, but then I get greedy and want n-ary 
application and the silver axe and the golden axe...

The final transition, from Applicative to Monad, is driven by a whole 
new level of greed. I received the gift of n-ary application and a 
silver axe and a golden axe; now I want a smart axe. Here is what I mean:

In the compound action

fs <*> xs

the sub-action fs cannot behave dependently on what "return value" the 
sub-action xs "returns". (Likewise for the other way round.) That data 
dependency is provided by Monad's (>>=) or (=<<). One operand can now 
peak at the "return value" of the other sub-action, and do some 
Turing-smart processing, before it decides what action to take.

This is my version of what other people call successively expanding API.

More information about the Haskell-Cafe mailing list