Friday, March 6, 2009

Monads Part 3

In functional programming, a monad is a kind of abstract data type used to represent computations (instead of data in the domain model). Programs written in functional style can make use of monads to structure procedures that include sequenced operations,[1][2] or to define arbitrary control flows (like handling concurrency, continuations, or exceptions).

Formally, a monad is constructed by defining two operations bind and return and a type constructor M that must fulfill several properties. These properties make possible the correct composition of functions that use values from the monad as their arguments (so called monadic functions). The monad acts as a framework in that it's a reusable behavior that decides the order in which the specific monadic functions are called, and manages all the undercover work required by the computation.[3]

The primary uses of monads in functional programming are to express input/output (I/O) operations and changes in state without using language features that introduce side effects[4]. 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. However, I/O and state management are by no means the only uses of monads. They are useful in any situation where the programmer wants to carry out a purely functional computation while a related computation is carried out "on the side." In imperative programming the side effects are embedded in the semantics of the programming language; with monads, they are made explicit in the monad definition.

The name monad derives from category theory, a branch of mathematics that describes patterns applicable to many mathematical fields. (As a minor terminological mismatch, the term "monad" in functional programming contexts is usually used with a meaning corresponding to that of the term "strong monad" in category theory, a specific kind of category theoretical monad.[citation needed])

The Haskell programming language is a functional language that makes heavy use of monads, and includes syntactic sugar to make monadic composition more convenient. All of the code samples below are written in Haskell unless noted otherwise.

Definition


A monad is a construction that, given an underlying type system, embeds a corresponding type system (called the monadic type system) into it (that is, each monadic type acts as the underlying type). This monadic type system preserves all significant aspects of the underlying type system, while adding features particular to the monad.

The usual formulation of a monad for programming is known as a Kleisli triple, and has the following components:

1. A type construction that defines, for every underlying type, how to obtain a corresponding monadic type. In Haskell's notation, the name of the monad represents the type constructor. If M is the name of the monad and t is a data type, then "M t" is the corresponding type in the monad.
2. A unit function that maps a value in an underlying type to a value in the corresponding monadic type. The result is the "simplest" value in the corresponding type that completely preserves the original value (simplicity being understood appropriately to the monad). In Haskell, this function is called return due to the way it is used in the do-notation described later. The unit function has the polymorphic type t→M t.
3. A binding operation of polymorphic type (M t)→(t→M u)→(M u), which Haskell represents by the infix operator >>=. Its first argument is a value in a monadic type, its second argument 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. The binding operation can be understood as having four stages:
a. The monad-related structure on the first argument is "pierced" to expose any number of values in the underlying type t.
b. The given function is applied to all of those values to obtain values of type (M u).
c. The monad-related structure on those values is also pierced, exposing values of type u.
d. Finally, the monad-related structure is reassembled over all of the results, giving a single value of type (M u).

In Object-oriented programming terms, the type construction would correspond to the declaration of the monadic type, the unit function takes the role of a constructor method, and the binding operation contains the logic necessary to execute its registered callbacks (the monadic functions).

In practical terms, a monad, unlike your everyday function result, stores function results and side-effect representations. This allows side effects to be propagated through the return values of functions without breaking the pure functional model. For example, Haskell's Maybe monad can have either a normal return value, or Nothing. Similarly, error monads (such as Either e, for some type e representing error information) can have a normal return value or an error value.

No comments:

Post a Comment