m a -> (a -> m b) -> m b
Okay, so what does this mean? I thought it was `f x -> x * x` is a function definition, right? Or am I completely mistaken here? Because in the above code, what is the function name, the parameter and the return value? I know "everything is a function" in Haskell but I really can't see through the multiple arrows here. Any help?First of all, this is a function declaration (ie. prototype), not a definition. So this is describing a function type, not a function implementation. But that doesn't help very much because it's still not very obvious what the function type means.
The shortcut way to understanding Haskell function declarations is this; if you see:
a -> b -> c -> d
in your head, think of it as: f(a, b, c) -> d
In other words, it is a function that takes three parameters of types a, b, and c and returns type d. Everything before the final -> is a parameter and the final type is a return type.My "shortcut" isn't literally true, obviously. Here is the gory detail.
In Haskell, every function takes at most one parameter. Functions of multiple parameters do not exist; they are simulated through a technique called "currying." When you think you're calling a function of more than one parameter, you're actually calling a series of functions, each of which takes exactly one parameter. So in Haskell, if you call:
f a b c
This is actually parsed as ((f a) b) c
Or in more C-like notation: f(a)(b)(c)
In other words, you call a function with a single parameter "a", which returns a function that you call with a single parameter "b", which returns a function that you call with a single parameter "c."Likewise, the Haskell type declaration:
a -> b -> c -> d
Is actually right-associative, so it's parsed as: a -> (b -> (c -> d)))
Which is why the whole thing works.So to parse:
m a -> (a -> m b) -> m b
Think of it as a function that would be called like so: f(m a, g) -> m b
Where g is a function that would be called like so: g(a) -> m b
The "m a" and "m b" business you can think of as being a lot like M<a> and M<b> in C++. (>>=) :: Monad m => m a -> (a -> m b) -> m b
So, >>= is a function that takes:- A value a in a monadic type m
- A function (a -> m b): a function that takes a value a and returns a value b wrapped in the monadic type m.
And it returns:
- A value b wrapped in the monadic type m.
It helps to look at the definition of (>>=) for a particular monad. The article mostly discusses computations that can fail (None vs an object in Python). The corresponding Haskell monads are Maybe and Either. The signature for (>>=) in the Maybe monad is:
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
What the grandparent points out is that a monad defines a structure (how to combine expressions that result in wrapped values), but not semantics. The semantics are defined in the definition of a particular monad. E.g. the Maybe monad models failure in computation, while a monad such as MonadRandom does something different altogether (providing random numbers, while threading the state of the random number generator). (>>=) :: Monad m => m a -> (a -> m b) -> m b
It's not the definition of >>=, though. The definition is left up to the specific Monad instance that's defining it (which is basically the larger point that I was trying to make).In English, that type signature basically says that >>= is a function which takes a monad and a function that operates on the monad's "contents" as its arguments, and returns the result of applying the function to the monad's contents. Any data type for which that abstract structure makes sense (and that also complies with the basic "monad laws") can be made an instance of Monad and provide its own definition for how >>= operates. That definition can be wildly different for different data types; the specific definition that the article focuses on is the one for the Maybe type.
In this case, it's a type signature for a curried function. So
a -> m b
is a function taking a value of type `a` and returning a value of type `m b`. In C# you would write: Function<A, M<B>>
so `m a -> (a -> m b) -> m b` is a function taking a value of type `m a` and a function with signature `a -> m b` and returning a function of type `m b`. Translating to C# again, Function< M<A>, Function<A, M<B>>, M<B> >
> Or am I completely mistaken here?Pretty much yeah. In haskell, a function is either a top-level binding:
someFunction arg = doSomething arg
or an anonymous function which is introduced by the character `\` (because `\` looks like `λ`, kind-of): \arg -> doSomething arg
In the expression you quoted, there is no function name, these are all types. The function name in this case is `(>>=)`For example,
data Maybe a = Nothing | Just a
- The m is for "Maybe"
- The a is for "a"
For example: (>>=) (Just 3) (\ x -> Just (show x))
should returns: Just "3". (>>=) Nothing (\x -> Just (show x))
better written Nothing >>= (\x -> Just (show x))
should returns: Nothinghttp://conal.net/blog/posts/everything-is-a-function-in-hask...
I think perhaps another reason why beginners find monads so hard to understand, especially those coming from a math background, is that >>= is a bizarre presentation of monads. I think, for example, defining a monad as an applicative with a join operation would have been a much better idea - most monads, like Maybe or [], make the most sense to me as "containers" that can be joined. The bind operator never really made intuitive sense to me when thinking about a monad as a container with a structure. Plus, to me, m (m a) -> m a is a lot easier to recognize than m a -> (a -> m b) -> m b.
This is especially true since applicatives are now becoming a very popular language idiom. It seems unfair to beginners to make them try to understand applicatives and then make them learn an unrelated typeclass for monads, when mathematically the two are very similar objects.
I tried to explain it here ( http://www.reddit.com/r/programming/comments/erzh1/monads_ar... ) a while ago, which might be helpful for some people. Although, the version of List's >>= function is much easier to understand here ( http://en.wikibooks.org/wiki/Haskell/Advanced_monads#The_Lis... ) than the one I pulled out of GHC's library code.
Beyond obeying some simple laws, there are strikingly few restrictions on the semantics of >>=. It can mean completely different things to different Monad instances. To me, that's at the heart of why newbies struggle to understand monads: >>= operates at a higher level of abstraction than many programmers are accustomed to. Outside of specific Monad instances, >>='s meaning is less significant than the structure that it imposes via the type system.
But that flexibility is also what makes Monad such a useful class in Haskell. Once your brain begins to recognize the `m a -> (a -> m b) -> m b` pattern in code, you see it everywhere. Monads are just a way of acknowledging that that particular structure exists in your code and abstracting it away to be replaced by a single operator. A chain of function calls with possible failure, like the author points out, is one case in which such a pattern emerges, but it's far from the only one. I think the article sort of misses that larger point.