Monads are basically a design pattern dealing with special data types. Let's say you're in some situation where there's nondeterminism—each function doesn't return just a value, but several possible values. To use a pseudo-C++-like type system, all of your functions have a signature like
List<B> doSomething(A);
where it returns a list of B's to represent every possible value. You want to chain these together, and the naïve way is
foo = doSomething(x)
bar = []
for someFoo in foo:
bar += doSomethingElse(someFoo);
baz = []
for someBar in bar:
baz += doSomeOtherThing(someBar)
So for every function, you have to repeatedly accumulate the possible values for every possible value so far. If you have higher-order functions, you can encapsulate this in a function like this
def bind(f, list):
results = []
for value in list:
results += f(value)
return results
which means the above example could be rewritten as
which is to say it takes a function from a normal type to a "special" type—in this case a list—and applies it to a "special" type—in this case, every element of a list. In this case, we'd say that List, together with the bind function, is monadic. The Haskell types look more like
bind :: (a -> m b) -> m a -> m b
-- or for our particular example
bind :: (a -> [b]) -> [a] -> [b]
The key here—and it's a simple example, so it's probably hard to see how it extends to the hype given—is that you've got a "special" kind of data and you're taking functions which operate on normal (non-special, in this case, non-list) data and writing functions to use them on special data with little work. The cool thing is that it's a really common pattern, which is why Haskell programmers mention it a lot.
(Note: in Haskell, 'bind' is actually an operator written >>=, and the order of its arguments are reversed, so its type is
>>= :: (Monad m) => m a -> (a -> m b) -> m b
but there are reasons for writing it the way I did.)
Monads are basically a design pattern dealing with special data types. Let's say you're in some situation where there's nondeterminism—each function doesn't return just a value, but several possible values. To use a pseudo-C++-like type system, all of your functions have a signature like
where it returns a list of B's to represent every possible value. You want to chain these together, and the naïve way is So for every function, you have to repeatedly accumulate the possible values for every possible value so far. If you have higher-order functions, you can encapsulate this in a function like this which means the above example could be rewritten as Now, the type of bind looks something like which is to say it takes a function from a normal type to a "special" type—in this case a list—and applies it to a "special" type—in this case, every element of a list. In this case, we'd say that List, together with the bind function, is monadic. The Haskell types look more like The key here—and it's a simple example, so it's probably hard to see how it extends to the hype given—is that you've got a "special" kind of data and you're taking functions which operate on normal (non-special, in this case, non-list) data and writing functions to use them on special data with little work. The cool thing is that it's a really common pattern, which is why Haskell programmers mention it a lot.(Note: in Haskell, 'bind' is actually an operator written >>=, and the order of its arguments are reversed, so its type is
but there are reasons for writing it the way I did.)