Monads Are Not Metaphors
codecommit.com
codecommit.com
In short, he has you using monads long before you understand them (Maybe and IO in particular), then slowly introduces monads by first explaining functors and applicative functors.
In retrospect, the mystique seems crazy. Monads are just not that confusing: they're simply values with added context, along with functions that let you interact with those values without losing the context. It's a shame that this powerful idea is so obscured by its supposed difficulty.
I don't think the 'what' is confusing, but the 'why and when'. Monads are a pattern; when I first learned about the Strategy Pattern, I understood it. It wasn't until a while later I started seeing the need for it and could explain why...
Also it's kinda pointless. If you go up to an improvising musician and tell them how amazing the hemiola cadence they just used was, they'd probably tell you to chill out and enjoy the music.
It's a leaky metaphor but it does reiterate the two levels of logic going on in a monad: the "boxed" value and the "box" itself.
This is a typical thing in mathematics.
And then, after you see the thing for what it is (months later), you start coming up with questions that lead to more formalism.
Studying from an encyclopaedia is hard, and even a good book will only get you as far as well-known results. Answers are much easier to learn from, so you want someone to provide you with the correct questions and avoid the difficult ones.
I disagree with this, and it was Eric Meijer's "Fundamentalist Functional Programming" lecture that really changed my mind. The point isn't that Haskell prevents side effects. It's that it requires you to be explicit about them. Indeed, some advocates say that Haskell is "the best imperative langauge". I don't know that I would go that far though.
It sounds like something to get the benefits of object-oriented programming while using functional programming, but I'm really confused.
Monads aren't a new thing, rather they're giving a name to a concept that has been hiding in plain sight. Trying to look at them directly is confusing at first, like suddenly being able to explicitly manipulate continuations.
A monad is a type that keeps some value contained, which is like you said a big part of object-oriented programming. Monads are the use of objects for encapsulation, but a bit more extensible than in regular object-oriented languages. The Maybe monad, called Option in the article, is a type that can hold either some value or Nothing. You have to do a null check to get the value, but because it's a monad, you can use the generic function bind to automate this check.
The IO monad is just another application of this idea of containing something - all IO operations have the world as their input and output. This is implicit in most languages, but in Haskell it's explicit. Any value you get from the outside world is hidden inside an IO action, but you can use bind to automate the required passing around of the world.
One possible reason for confusion is that you can explicitly do null checks with Maybe but you can't explicitly thread the world around with IO. Maybe's method of direct access is public, but IO's is private. Because the /only/ way to get a value out of an IO operation is with bind, you are guaranteed to have all side effects contained in IO actions.
Monads are the name for a particular member of a forth level on that three-level stack of abstractions (call them type classes, as that's what Haskell calls them (though I'm fudging a little here)); a type class is a particular shape for a generic type, in the same way that any given generic type is a particular shape for a class, and a class is a particular shape for an instance.
So when people talk about Option/Maybe being a monad, they mean Option/Maybe is a generic type (i.e. a type constructor) which has a certain shape - i.e. has a particular set of methods / functions defined on it.
That's the abstraction level of monads out of the way. The next thing to understand is the particular operations required. Monads are like containers for values, but rather than operating on the values directly (e.g. y = f(x)), you instead pass the monad the function you'd like it to apply to the value (e.g. y = x.bind(f)), and it returns you a monad which is logically the wrapper that function applied to its contents.
Because the application of the function to the value inside the monad is delegated to the monad itself, it gets to decide what to do with it. In the case of Option/Maybe, it'll only apply the function if the contents aren't empty. In the case of IO, it'll logically buffer up a list of imperative I/O operations which will be logically returned as a result of the main function; and that list of imperative instructions will then be imperatively executed, after the nice and pure Haskell program has finished its unpolluted existence. (That's how it happens logically (assuming there are no cheats available in the language), but not necessarily actually.)
But what I still don't understand is how monads force sequencing more so than regular function calls and expression evaluation. The very first example is about sequencing but there doesn't seem to be much explanation of how monads are usueful for inducing sequencing in a lazy pure functional context.
It is very tempting to try to jump quickly to 2 - but it helps to force yourself to avoid thinking about applications for a bit and understand the applications.
I think the article does achieve this.
http://ngrams.googlelabs.com/graph?content=monad%2CHaskell...
2nd wave, monad tutorial fallacy, red herring, don't read/write monad tutorials, they just sort of grow on you! e.g.
http://www.haskell.org/haskellwiki/Monad_tutorials_timeline
http://news.ycombinator.com/item?id=336085
http://byorgey.wordpress.com/2009/01/12/abstraction-intuitio...
So here it is: http://www.scala-lang.org/docu/files/ScalaTutorial.pdf
sealed trait Option[+A] {
def bind[B](f: A => Option[B]): Option[B]
(My best guess: define a trait named `Option` ... something about an object of type A ... really not sure of the +. Then define a function `bind` that ... something about type `B` ... which takes an argument of type `f`? and returns the argument wrapped in an Option?)the Option type defines a method `bind` (I'll come back to the type B) which takes a function f that takes something of type A and returns something of type Option[B], no matter what B is (Scala makes you declare the type parameters you use in a function's arguments in the beginning (after its name)).
I found that explaining bind works best with a more familiar type like List.
if we have a type List of A's, and to simplify further, let's say that A is Int, so we have a List of Ints, then bind is a function that applies its argument, the latter being a function itself, on all its elements, and merging the resulting lists together. Suppose we pass the function `f` that for an Int returns the int itself and its double to the bind function of the following list: [1, 10, 100]
In the first step, the function f is applied to all the list elements: [[1, 2], [10, 20], [100, 200]] Than flattens it so we end up with: [1, 2, 10, 20, 100, 200].