
Free and Freer Monads: Putting Monads Back into Closet - alphonse23
http://okmij.org/ftp/Computation/free-monad.html
======
michaelsbradley
The web page mentions a "Haskell Symposium 2015 paper". I didn't see it linked
from the page, but I'm fairly certain it's this one:

 _Freer Monads, More Extensible Effects_

[http://okmij.org/ftp/Haskell/extensible/more.pdf](http://okmij.org/ftp/Haskell/extensible/more.pdf)

~~~
michaelsbradley
The conclusion is pretty bold:

"The ambition is for Eff [the extensible freer monad, the monad of extensible
effects] to be the only monad in Haskell. Rather than defining new monads
programmers will be defining new effects, that is, effect interpreters."

~~~
Kutta
Eff needs some additional optimization or some extra compiler support before
it can thrive in the wild, because the constant overheads are pretty severe.
The asymptotic overheads though are really good, basically they managed to get
rid of all possible time complexity blowups with the last Eff refinement that
added type-aligned sequences.

~~~
chowells
Eff has a bigger semantic issue to deal with first.

It is only composable for commutative effects. Once you introduce non-
commutative effects like throw/catch or nondeterminism, the semantics of a
block of code using more than one effect depends on the order in which
interpreters are run.

Monad transformers escape this issue by allowing code to specify the effect
nesting order in the type. They're no panacea either, of course. But they
currently allow somewhat better code reuse and abstraction properties than the
Eff approach does.

If Eff ever gets the ability to control the semantics of non-commutative
effects, it will have a much more compelling story.

~~~
Kutta
It's not particularly worse than monad transformers with respect to non-
commutative effects. With monad transformers, one can trip up just as happily
on exceptions, and mtl-style stack-polymorphic code can be run with various
effect orderings with possibly varying semantics.

I failed to mention though that Eff would also benefit from some boost to type
inference for open sums. Currently it's throwing up hands for component
effects with polymorphic inner type parameters, like `State s` or `Reader r`,
so we can't do things like `put 0`, but only `put (0 :: Int)` (in the absence
of other type annotations in outer scopes). It's fortunately not an impossible
problem; we just need to allow for unique projections from sums in our type-
level machinery (this requires some annoying boilerplate currently, but maybe
GHC 8.0 will make it easier with the new kind system).

~~~
chowells
Yes, transformers allow you to get it wrong, too. But at least there is a way
to get it right with them.

------
skybrian
Perhaps there's little math, but there's an intimidating amount of Haskell
jargon. Are there any lessons for people writing in other languages?

~~~
seagreen
This paper is over my head, but in case anyone is wondering what Free monads
are I can give a teaser for how they're useful.

Say you're automating a bio lab. You're writing software to control
evacuations. The lab machinery can execute two actions (1) Alarm (sets off an
evacuation alarm in an area) (2) Sterilize (burns an area with fire).
Obviously we would like to call (1) for an area well before we call (2).

To these two actions we can add one of our own: (3) Wait (for some number of
seconds).

Now we write a function (using Haskell types, but they're easy to read):

    
    
      evacuate :: ContaminationInfo -> IO ()
    

This function takes in the state of a lab (what areas have been contaminated,
what areas are at risk, etc.) makes an evacuation plan, and executes it.

Now, the first things you notice is that _this is a horrible function_. How
could we test it? We would need an actual lab (or mocks, but that's no fun).

Let's try again.

    
    
      makePlan :: ContaminationInfo -> [Action]
    

(Where action is either `Alarm Area`, `Sterilize Area`, or `Wait Seconds`)

This is way better! Now we can write interpreters for `[Action]`.

    
    
      testContaminationPlan :: [Action] -> TestResults
    
      prettyPrintContaminationPlan :: [Action] -> String
    
      graphContaminationPlan :: [Action] -> SVG
    
      runContaminationPlan :: [Action] -> IO ()
    

Note that all of this can be done in Python, which is pretty cool! Sadly we
can't write `makePlan :: ContaminationPlan -> [Action]` in Python though. It
would have to be `makePlan :: ContaminationPlan -> IO [Action]`, which means
that there could be side effecting functions that slip by the programmer and
aren't reflected in the return type. If one of these is Sterilize someone
could have a bad day:(

Now lets say our wonderful engineers build us an excellent new action: (4)
Scan (check an area for risk of contamination).

Now our [Action] plan starts to break down. Before an [Action] was very
simple. An example might have been [Alarm Area1, Alarm Area2, Wait 200
Seconds, Sterilize Area1, Sterilize Area2].

But our scanner allows later actions to depend on the result of previous
actions! [Action] isn't sufficient to model that -- how would our interpreters
know how to thread things together (our goal is to be able to do things like
start scanning an at-risk room like crazy, but not actually evacuate it unless
contamination appears).

If only we had some way for our data type to reflect that some actions might
need to be fed into others? Hmm, I wonder what we could use for that ...

~~~
seagreen
PS Pretty much all my knowledge of this subject (and the pretty printing
interpreter example in particular) comes from here:
[http://www.haskellforall.com/2012/06/you-could-have-
invented...](http://www.haskellforall.com/2012/06/you-could-have-invented-
free-monads.html)

