A list is not a monad — it’s just a container of values, ie. a functor. A monad is a data structure defines a computation in a specific context, and allows composing these in a sequential manner. For example, the Haskell IO monad is a computational context in which you can do input/output, and all of these IO operations are represented using a data structure of the type “IO <return_value>”.
For example, the function “readLine” has the type “IO String”, and represents a computation that reads a line from standard input and returns it as a string. At runtime, evaluating this value will result in the runtime system asking the user for some input, and at compile-time this is represented as the string (that the user enters at runtime) inside the IO monad.
Huh? List is very much a monad.
But I can't make sense of the definition of >>= for the list in Haskell, which is:
xs >>= f = [y | x <- xs, y <- f x]
It seems to imply that I get a list in return when I do xs >>= f, but I need to do the following in order for it to work: [1,2,3] >>= return . (+1) > [1,-2,3] >>= (\x -> replicate (abs x) x)
[1,-2,-2,3,3,3]Is there a resource for this ? or good old intuition ?
Just remember Absolutely ANY design pattern / data structure can be a monad as long as you can get an internal value out of that abstraction and define a bind operator to compose monads together.
This rule tells it all:
(>>=) :: m a -> (a -> m b) -> m b
m is the abstraction wrapper and a is the internal thing that is wrapped. You can wrap it in a type string, a list. Even like a binary tree can be a monad.You can define the bind operator to do whatever you want, it just needs to follow the type signature above and be associative.
As an example, a maybe monad in python can be implemented by having a monadic function return either:
and the bind operator (>>=) would be: You should also understand that a list itself can be a monad. Monads are just burritos where ANY abstraction/design pattern can be the wrapping, it does not need a haskell type system to wrap something. Albeit the type system in haskell does really help you grok the concept.Weirdly how someone chooses to implement a monadic value and the bind operator suffers from the same problem as what this article writer complains about in OOP design patterns. Both monads and design patterns really depend on previous understanding of a pattern, and a variation on how someone chooses to implement the bind operator or a design pattern can really throw off people.
Here is an example of an alternative variation of the "Maybe" monad in python, for the return values:
And a variation on bind: