6 ms·
Perhaps the author is just glossing over the bigger picture for the sake of explanation, but it's a bit of a narrow view of monads to say that they are just "co
by tmhedberg 15y ago
Perhaps the author is just glossing over the bigger picture for the sake of explanation, but it's a bit of a narrow view of monads to say that they are just "conditional function calls". That's true if the monad in question is Maybe, Either e, or (if you're squinting at it just right) []. But >>= in the State s and IO monads, for instance, has little to do with conditionally calling functions; there, it's more about sequencing.
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.
- tripzilch 15y agom 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?
- tmhedberg 15y agoSorry for not being clear. That's just the (abbreviated) type signature of >>=, which is formally written as (>>=) :: 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.
- deleted 15y ago[deleted]
- yogsototh 15y agom a: means a type which take a parameter (another type). 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: Nothing
- danieldk 15y agoIt's actually more insightful to see the full type signature: (>>=) :: 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).
- masklinn 15y ago> 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? 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 `(>>=)`
- haberman 15y agoThis is one of those things that functional-programming people seem to "get" without ever making the explanation very clear. 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++.
- tripzilch 15y agoThank you! It's coming back to me now :) This was taught to me in college, I know about currying, the right-associativity was the big part I missed!
- deleted 15y ago[deleted]
- jamiltron 15y agoNot to be nit-picky, but everything is Haskell is not always a function: http://conal.net/blog/posts/everything-is-a-function-in-haskell http://conal.net/blog/posts/everything-is-a-function-in-hask...
- Figs 15y agoActually, I'm pretty sure the reason most people have trouble understanding monads in Haskell is because they haven't learned what typeclasses are yet. Once you know what a typeclass is, the rest is pretty straightforward. I tried to explain it here ( http://www.reddit.com/r/programming/comments/erzh1/monads_are_not_metaphors/ 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_List_monad http://en.wikibooks.org/wiki/Haskell/Advanced_monads#The_Lis... ) than the one I pulled out of GHC's library code.
- rmcclellan 15y agoI completely agree. It's hard for beginners to learn that a monad isn't a thing, it's an property that can apply to many different things. A monad is so general it's hard to have a single intuition about it. 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.