A simple introduction to why Monads are useful
The operations that define the monad must fulfil several properties to allow the correct composition of monadic functions (i.e. functions that use values from the monad as their arguments or return value). Because a monad can insert additional operations around a program's domain logic, monads can be considered a sort of aspect-oriented programming.[8] The domain logic can be defined by the application programmer in the pipeline, while required aside bookkeeping operations can be handled by a pre-defined monad built in advance. In a purely functional language, such as Haskell, functions cannot have any externally visible side effects as part of the function semantics. Although a function cannot directly cause a side effect, it can construct a value describing a desired side effect, that the caller should apply at a convenient time.[10] In the Haskell notation, a value of type M a with a function of type a ° M b to create a monadic value of type M a with a function of type a ° M b to create a monadic value of type M a can be thought of as an action that returns a value of type a. We can think of a value of type M a can be thought of as an action that returns a value of type IO a represents an action that, when performed, produces a value of type a. We can think of a value of type a; the operand on the left is an I/O action that prints two lines of text to the console. The type of >> is IO a ° IO b ° IO b, meaning that the operator takes two I/O operations and returns a third that sequences the two together and returns the value of the second. We should have an I/O action which does nothing. That is, it returns a value but has no side effects. In Haskell, this action constructor is called return; it has type a ° IO a. The function then creates a new monadic value M b that can be fed to the next bind operators composed in the pipeline. With these elements, the programmer composes a sequence of function calls (the "pipeline") with several bind operators chained together in an expression. Each function call transforms its input plain type value, and the bind operator handles the returned monadic value, which is fed into the next step in the sequence. Between each pair of composed function calls, the bind operator can inject into the monadic value some additional information that is not accessible within the function, and pass it along. It can also exert finer control of the flow of execution, for example by calling the function only under some conditions, or executing the function calls in a particular order. For example, the following code defines a binary operator x//y as safe division that avoids dividing by zero, using the Maybe monad and its constructors Nothing and Just.[a] The monadic values x and y are extracted into the plain values a and b, which are processed by the plain division operator "/" only when b is not zero. In the third example expression, a pipeline that chains together two safe divisions, the result of the first division is Nothing, which is fed as the input value to the second "//" operator; therefore the result is Nothing as well. Notice how the definition of the "//" operator doesn't need to check whether any of its input values is Nothing, as the bind operator of the Maybe monad already handles this concern: by definition of bind, when either the x or the y monadic parameters are Nothing (instead of matching the pattern Just value), the "if b == 0 ..." function is not executed. The operations that define the monad must fulfil several properties to allow the correct composition of monadic functions (i.e. functions that use values from the monad as their arguments or return value). Because a monad can insert additional operations around a program's domain logic, monads can be considered a sort of aspect-oriented programming.[8] The domain logic can be defined by the application programmer in the pipeline, while required aside bookkeeping operations can be handled by a pre-defined monad built in advance. In a purely functional language, such as Haskell, functions cannot have any externally visible side effects as part of the function semantics. Although a function cannot directly cause a side effect, it can construct a value describing a desired side effect, that the caller should apply at a convenient time.[10] In the Haskell notation, a value of type IO a represents an action that, when performed, produces a value of type a; the operand on the right is a function that can pick an I/O action based on the results of previous actions. To do this, Haskell has an operator >>= (pronounced bind) with type IO a ° (a ° IO b) ° IO b. That is, the operand on the left is an I/O action that prints two lines of text to the console. The type of >> is IO a ° IO b ° IO b, meaning that the operator takes two I/O operations and returns a third that sequences the two together and returns the value of the second. We should be able to sequence two I/O operations together. In Haskell, this is written as an infix operator >>, so that putStrLn "abc" >> putStrLn "def" is an I/O action that prints two lines of text to the console. The type of >> is IO a ° IO b ° IO b, meaning that the operator takes two I/O operations and returns a third that sequences the two together and returns the value of the second. We should be able to determine our next action based on the results of previous actions. To do this, Haskell has an operator >>= (pronounced bind) with type IO a ° (a ° IO b) ° IO b. That is, the operand on the right is a function that maps from the underlying type of the first argument to another monadic type, and its result is in that other monadic type. Typically, the binding operation can be understood as having four stages: [1..2] The binary bind operation ">>=" takes as its arguments a monadic value M a and a function (a ° M b) that can transform the value. The unary return operation takes a value from a plain type and puts it into a container using the constructor, creating a monadic value: M a. The given function is applied to all of those values to obtain values of type (M u). return Nothing; return Something(value); }; With this new bind method we can more elegantly re-write our code: var state = Maybe(person).bind(function(p) { return s; })); And now we have our final solution. But is Maybe a Monad? Thus far, I've been calling our Maybe implementation a monad without really proving it. Nevertheless, hopefully you now have at least a vague sense of what a monad is, even if I haven't presented any kind of formal definition. So, what is a monad? Perhaps the most intuitive way to think about monads is as chainable computations, or even "programmable semicolons." They allow us to wrap up computations and sequence them in meaningful ways. In the case of the Maybe monad, the computations that we choose to wrap up are our != null checks, and we sequence them through our chained use of bind. Of course, monads may also be defined more formally. For our Maybe example to truly be a monad it must have three particular properties and obey three particular laws. Of the three properties it must: Have a binding operation that takes a monad, a function that takes a some type and returns a monad, and returns a monad. This is our bind function. (Again, note that in our example, the function type signature varies slightly from this definition, as we automatically wrap the result of our binding function in Maybe.) As for the three laws, these are known as: left identity, right identity, and associativity.