| dbpprop:abstract
|
- In functional programming, a monad is a kind of abstract data type used to represent computations (instead of data in the domain model). Monads allow the programmer to chain actions together to build a pipeline, in which each action is decorated with additional processing rules provided by the monad. Programs written in functional style can make use of monads to structure procedures that include sequenced operations, or to define arbitrary control flows. Formally, a monad is constructed by defining two operations (bind and return) and a type constructor M that must fulfill several properties to allow the correct composition of monadic functions (i.e. functions that use values from the monad as their arguments). The return operation puts a value from a plain type into a monadic container of type M. The bind operation performs the reverse process, extracting the original value from the container and passing it to the associated next function in the pipeline. The following pseudocode shows a usage example of a monad. It uses a special division operator // to perform a sequence of divisions. The // operator checks whether the divisor is 0, in which case it returns a special value Nothing that is chained through the other operations in the procedure. The // operator is defined in terms of the constructor and operators of the Maybe monad explained later. safeDivisions x do val1 <- 6' // x' val2 <- 3' // 1' val3 <- val1' // val2' return val3 safeDivisions 2 safeDivisions 0 -> Nothing The values 6', 3', 1' and the variables x', val1', val2' are modified versions of the equivalent numbers transformed to match the correct type required by the // operator. Operations on the transformed values are augmented with the error-control aspect provided by the Maybe monad. 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. Background 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. 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. {{fact|dateDecember 2007) 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. Motivation Consider a function, such as division, which is undefined for some known values, such as zero. Division might occur repeatedly in a calculation, like this one, which returns the resistance of two electrical resistors in parallel: -- par is a function that takes two real numbers and returns another -- It is an example taken from electrical engineering (see above) to -- illustrate why implementing NaN-semantics on top of the current -- division system is useful; it is not related to Monads. par :: Float -> Float -> Float -- resistance(A), resistance(B) -> resistance(A in parallel with B) par x y 1 / (+) -- formula given from electrical engineering Instead of avoiding any errors by checking whether each divisor is zero, it might be convenient to have a modified division operator that does the check implicitly, as in the following pseudocode: -- // is an operator that takes two "Maybe Float"s and returns another. -- "Maybe Float" extends the Float type to represent calculations that may fail. (//) :: Maybe Float -> Maybe Float -> Maybe Float x // y ... -- the definition appears below. par :: Float -> Float -> Maybe Float par x y 1' // (+') -- where 1', x', y' are the "Maybe" versions of 1, x, y and +' "adds" Maybe Floats. -- See below for details. With the // operator, dividing by zero anywhere in the computation will result in the entire computation returning a special value of the Maybe monad called "Nothing", which indicates a failure to compute a value. Otherwise, the computation will produce a numerical result, contained in the other Maybe value, which is called "Just". The result of this division operator can then be passed to other functions. This concept of "maybe values" is one situation where monads are useful. Concepts 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: 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. 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. 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: The monad-related structure on the first argument is "pierced" to expose any number of values in the underlying type t. The given function is applied to all of those values to obtain values of type (M u). The monad-related structure on those values is also pierced, exposing values of type u. 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, a normal 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. Examples Consider how these apply to the example of "Maybe", the option type. A Maybe type is just the underlying type (represented by wrapping with "Just"), and a value representing "nothing", i.e. undefined. data Maybe t Just t | Nothing The Maybe value corresponding to an underlying value, is just that value (represented by wrapping with "Just"). return x Just x Binding a function to something that is just a value means applying it directly to that value (the function must return a monadic type). Binding a function to nothing produces nothing. mBind :: Maybe a -> (a -> Maybe b) -> Maybe b (Just x) `mBind` f f x Nothing `mBind` f Nothing For the safe division example, "(/)" is the underlying function, "(//)" is the safe monadic version. There are two Maybe inputs. If either input is "Nothing", then "Nothing" is returned. Otherwise the inputs are Just a and Just b, from which a and b are extracted. If b is zero, (/) cannot be applied, so "Nothing" is returned, otherwise "Just (a / b)" is returned: (//) :: Maybe a -> Maybe a -> Maybe a _ // Nothing Nothing Nothing // _ Nothing _ // Just 0 Nothing Just x // Just y Just (x / y) A more general version that applies to all types m such that m is an instance of the Monad class: (//) :: (Fractional a, Monad m) > a -> a -> m a _ // 0 fail "//: divide by zero" x // y return (x / y) This is the definition of the same Maybe monad in the F# language: <source lang"ocaml-brief">type MaybeBuilder member this. Bind(x, f) match x with | Some(x) -> f(x) | _ -> None member this. Delay(f) f member this. Return(x) Some x let maybe MaybeBuilder Axioms For a monad to behave correctly, the definitions must obey a few axioms. (The ≡ symbol is not Haskell code, but indicates an equivalence between two Haskell expressions. ) "return" must preserve all information about its argument. (return x) >> f ≡ f x m >> return ≡ m Binding two functions in succession is the same as binding one function that can be determined from them. (m >> f) >> g ≡ m >> (\x ->) In the last rule, the notation \x -> defines an anonymous function that maps any value x to the expression that follows. In mathematical notation, the axioms are: <math>(\mathrm{lift \; x) \gg\! f \equiv f \; x</math> <math>m \gg\! \mathrm{lift \equiv m</math> <math>(m \gg\! f) \gg\! g \equiv m \gg\! \lambda x \; . \; (f \, x \gg\!\! g)</math> Monadic zero A monad can optionally define a "zero" value for every type. Binding a zero with any function produces the zero for the result type, just as 0 multiplied by any number is 0. mzero >> f ≡ mzero Similarly, binding any m with a function that always returns a zero results in a zero m >> (\x -> mzero) ≡ mzero Intuitively, the zero represents a value in the monad that has only monad-related structure and no values from the underlying type. In the Maybe monad, "Nothing" is a zero. In the List monad, "" (the empty list) is a zero. An additive monad is a monad endowed with a monadic zero and an operation (called mplus) satisfying the monoid laws, with the monadic zero as unit. The operation has type M t → M t → M t (where M is the monad constructor and t is the underlying data type), satisfies the associative law and has the zero as both left and right identity. An additive monad is also a monoid. do-notation Although there are times when it makes sense to use >> directly in a program, it is more typical to use a format called do-notation, that mimics the appearance of imperative languages. The compiler translates do-notation to expressions involving >>. For example, the following code: a do x <- [3..4] return (x, 42) is transformed during compilation into: a [3..4] >> (\x -> >>) It is helpful to see the implementation of the list monad, and to know that concatMap maps a function over a list and concatenates (flattens) the resulting lists: instance Monad where m >> f concatMap f m return x [x] fail s Therefore, the following transformations hold: a [3..4] >> (\x -> >>) a [3..4] >> (\x -> concatMap) a [3..4] >> (\x ->) a concatMap (\x ->) [3..4] a [(3,42),(3,42),(4,42),(4,42)] Notice that the list is not used. The lack of a left-pointing arrow, translated into a binding to a function that ignores its argument, indicates that only the monadic structure is of interest, not the values inside it; for the list monad this is trivial, but e.g. for a state monad this might be used for changing the state without producing any more result values. The do-block notation can be used with any monad as it is simply syntactic sugar for >>. The following definitions for safe division for values in the Maybe monad are also equivalent: x // y do a <- x -- Extract the values "inside" x and y, if there are any. b <- y if b 0 then Nothing else Just (a / b) x // y x >> (\a -> y >>) A similar example in F# using a computation expression: let readNum let s Console. ReadLine let succ,v Int32. TryParse(s) if (succ) then Some(v) else None let secure_div maybe { let! x readNum let! y readNum if (y 0) then None else return (x / y) The syntactic sugar of the maybe block would get translated internally to the following expression: maybe. Delay(fun -> maybe. Bind) The monad axioms become considerably clearer when translated to do-notation: do { v <- return x; f v do { f x do { v <- m; return v do { m do { y <- do { x <- m; f x; g y do { x <- m; y <- f x; g y Generic monadic functions Given values produced by safe division, we might want to carry on doing calculations without having to check manually if they are Nothing (i.e. resulted from an attempted division by zero). We can do this using a "lifting" function, which we can define not only for Maybe but for arbitrary monads. In Haskell this is called liftM2: liftM2 :: Monad m > (a -> b -> c) -> m a -> m b -> m c liftM2 op mx my do x <- mx y <- my return (op x y) Recall that arrows in a type associate to the right, so liftM2 is a function that takes a binary function as an argument and returns another binary function. The type signature says: If m is a monad, we can "lift" any binary function into it. For example: (.*. ) :: Monad m > m Float -> m Float -> m Float x .*. y liftM2 (*) x y defines an operator (.*. ) which multiplies two numbers, unless one of them is Nothing (in which case it again returns Nothing). The advantage here is that we need not dive into the details of the implementation of the monad; if we need to do the same kind of thing with another function, or in another monad, using liftM2 makes it immediately clear what is meant. Mathematically, the liftM2 operator is defined by: <math>\mathrm{liftM2 \colon \forall M \colon \mathrm{monad, \; (A_1 \to A_2 \to R) \to M \, A_1 \to M \, A_2 \to M \, R </math><math> op \mapsto m_1 \mapsto m_2 \mapsto \mathrm{bind \; m_1 \; (a_1 \mapsto \mathrm{bind \; m_2 \)</math> Examples Maybe monad The Maybe monad has already been defined above. The following definitions complete the original motivating example of the "par" function. add x y do x' <- x y' <- y return (x' + y') par x y let one return 1 jx return x jy return y in one // (add) If the result of any division is Nothing, it will propagate through the rest of the expression. The // operator actually requires parameters of type Maybe a, so the pseudocode example in the introduction paragraph is invalid. Here is the correct version which lifts values of the basic type into monadic ones: safeDivisions x do val1 <- return 6 // return x val2 <- return 3 // return 1 val3 <- val1 // val2 return val3 Identity monad The simplest monad is the identity monad, which attaches no information to values. Id t t return x x x >> f f x A do-block in this monad performs variable substitution; do {x <- 2; return 3*x results in 6. Collections Some familiar collection types, including lists, sets, and multisets, are monads. The definition for lists is given here. -- "return" constructs a one-item list. return x [x] -- "bind" concatenates the lists obtained by applying f to each item in list xs. xs >> f concat (map f xs) -- The zero object is an empty list. mzero List comprehensions are a special application of the list monad. For example, the list comprehension [ 2*x | x <- [1.. n], isOkay x] corresponds to the computation in the list monad do {x <- [1.. n]; if isOkay x then return else mzero; return (2*x). The notation of list comprehensions is similar to the set-builder notation, but sets can't be made into a monad, since there's a restriction on the type of computation to be comparable for equality, whereas a monad does not put any constraints on the types of computations. Actually, the Set is a restricted monad. The monads for collections naturally represent nondeterministic computation. The list (or other collection) represents all the possible results from different nondeterministic paths of computation at that given time. For example, when one executes x <- [1,2,3,4,5], one is saying that the variable x can non-deterministically take on any of the values of that list. If one were to return x, it would evaluate to a list of the results from each path of computation. Notice that the bind operator above follows this theme by performing f on each of the current possible results, and then it concatenates the result lists together. Statements like if condition x y then return else mzero are also often seen; if the condition is true, the non-deterministic choice is being performed from one dummy path of computation, which returns a value we are not assigning to anything; however, if the condition is false, then the mzero monad value non-deterministically chooses from 0 values, effectively terminating that path of computation. Other paths of computations might still succeed. This effectively serves as a "guard" to enforce that only paths of computation that satisfy certain conditions can continue. So collection monads are very useful for solving logic puzzles, Sudoku, and similar problems. In a language with lazy evaluation, like Haskell, a list is evaluated only to the degree that its elements are requested: for example, if one asks for the first element of a list, only the first element will be computed. With respect to usage of the list monad for non-deterministic computation that means that we can non-deterministically generate a lazy list of all results of the computation and ask for the first of them, and only as much work will be performed as is needed to get that first result. The process roughly corresponds to backtracking: a path of computation is chosen, and then if it fails at some point (if it evaluates mzero), then it backtracks to the last branching point, and follows the next path, and so on. If the second element is then requested, it again does just enough work to get the second solution, and so on. So the list monad is a simple way to implement a backtracking algorithm in a lazy language. I/O A monad for I/O operations is usually implemented in the language implementation rather than being defined publicly. The following example demonstrates the use of an I/O monad to interact with the user. do putStrLn "What is your name?" name <- getLine putStrLn ("Nice to meet you, " ++ name ++ "!") State monads A state transformer monad allows a programmer to attach state information of any type to a calculation. Given any value, the corresponding value in the state transformer monad is a function that accepts a state, then outputs another state along with a value. type StateTrans s t s -> (t, s) Note that this monad, unlike those already seen, takes a type parameter, the type of the state information. The monad operations are defined as follows: -- "return" produces the given value without changing the state. return x \s -> (x, s) -- "bind" modifies transformer m so that it applies f to its result. m >> f \r -> let (x, s) m r in (f x) s Useful state transformers include: readState \s -> (s, s) -- Examine the state at this point in the computation. writeState x \s -> (x) -- Replace the state. Another operation applies a state transformer to a given initial state: applyTrans:: StateTrans s a -> s -> (a, s) applyTrans t s t s do-blocks in a state monad are sequences of operations that can examine and update the state data. Informally, a state monad of state type S maps the type of return values T into functions of type <math>S \rarr T \times S</math>, where S is the underlying state. The return function is simply: <math>\mathrm{return \colon T \rarr S \rarr T \times S t \mapsto s \mapsto (t, s)</math> The bind function is: <math>\mathrm{bind \colon (S \rarr T \times S) \rarr (T \rarr S \rarr T' \times S) \rarr S \rarr T' \times S m \mapsto k \mapsto s \mapsto (k \, t \, s') \quad \mathrm{where \; (t, s') m \, s</math>. Environment monad The environment monad (also called the reader monad and the function monad) allows a computation to depend on values from a shared environment. The monad type constructor maps a type T to functions of type E → T, where E is the type of the shared environment. The monad functions are: <math>\mathrm{return \colon T \rarr E \rarr T t \mapsto e \mapsto t</math> <math>\mathrm{bind \colon (E \rarr T) \rarr (T \rarr E \rarr T') \rarr E \rarr T' r \mapsto f \mapsto e \mapsto f \, (r \, e) \, e</math> The following monadic operations are useful: <math>\mathrm{ask \colon E \rarr E \mathrm{id_E</math> <math>\mathrm{local \colon (E \rarr E) \rarr (E \rarr T) \rarr E \rarr T f \mapsto c \mapsto e \mapsto c \, (f \, e)</math> The ask operation is used to retrieve the current context, while local executes a computation in a modified subcontext. As in the state monad, computations in the environment monad may be invoked by simply providing an environment value and applying it to an instance of the monad. Writer monad The writer monad allows a program to compute various kinds of auxiliary output which can be "composed" or "accumulated" step-by-step, in addition to the main result of a computation. It is often used for logging or profiling. Given the underlying type T, a value in the writer monad has type W × T, where W is a type endowed with an operation satisfying the monoid laws. The monad functions are simply: <math>\mathrm{return \colon T \rarr W \times T t \mapsto (\epsilon, t)</math> <math>\mathrm{bind \colon (W \times T) \rarr (T \rarr W \times T') \rarr W \times T' (w, t) \mapsto f \mapsto (w * w',\, t') \quad \mathrm{where \; (w', t') f \, t</math> where ε and * are the identity element of the monoid W and its associative operation, respectively. The tell monadic operation is defined by: <math>\mathrm{tell \colon W \rarr (W \times 1) w \mapsto (w)</math> where 1 and denote the unit type and its trivial element. It is used in combination with bind to update the auxiliary value without affecting the main computation. Continuation monad A continuation monad with return type <math>R</math> maps type <math>T</math> into functions of type <math>\left(T \rarr R \right) \rarr R</math>. It is used to model continuation-passing style. The return and bind functions are as follows: <math>\mathrm{return \colon T \rarr \left(T \rarr R \right) \rarr R t \mapsto f \mapsto f \, t</math> <math>\mathrm{bind \colon \left(\left \rarr R \right) \rarr \left(T \rarr \left \rarr R \right) \rarr \left(T' \rarr R \right) \rarr R</math><math> c \mapsto f \mapsto k \mapsto c \, \left(t \mapsto f \, t \, k \right)</math> The call-with-current-continuation function is defined as follows: <math>\textrm{call/cc \colon \left(\left \rarr \left \rarr R \right) \rarr \left(T \rarr R \right) \rarr R</math><math> f \mapsto k \mapsto \left(f \left \, k \right)</math> Others Other concepts that researchers have expressed as monads include: Exception handling Graphical user interfaces Interprocess communication Parsers Interpreters Strict evaluation Interfaces to code written in other languages fmap and join Although Haskell defines monads in terms of the "return" and "bind" functions, it is also possible to define a monad in terms of "return" and two other operations, "join" and "fmap". This formulation fits more closely with the definition of monads in category theory. The fmap operation, with type (t→u) → (M t→M u), takes a function between two types and produces a function that does the "same thing" to values in the monad. The join operation, with type M (M t)→M t, "flattens" two layers of monadic information into one. The two formulations are related as follows. As before, the ≡ symbol indicates equivalence between two Haskell expressions. (fmap f) m ≡ m >> (\x -> return) join m ≡ m >> id m >> f ≡ join (m) The fmap function is defined for any Functor in the category of types and functions, not just for monads. It is expected to satisfy the functor laws: fmap id id fmap (f . g) (fmap f) . (fmap g) In addition, the following laws characterize monads: join . fmap join join . join join . fmap return join . return id return . f fmap f . return join . fmap (fmap f) fmap f . join History Eugenio Moggi first described the general use of monads to structure programs. Several people built on his work, including programming language researchers Philip Wadler and Simon Peyton Jones (both of whom were involved in the specification of Haskell). Early versions of Haskell used a problematic "lazy list" model for I/O, and Haskell 1.3 introduced monads as a more flexible way to combine I/O with lazy evaluation. In addition to IO, scientific articles and Haskell libraries have successfully applied monads to topics including parsers and programming language interpreters. The concept of monads along with the Haskell do-notation for them has also been generalized to form arrows. Haskell and its derivatives have been for a long time the only major users of monads in programming. There exist formulations also in Scheme and Perl, and monads have been an option in the design of a new ML standard. Recently the research language F# has included a feature called computation expressions or workflows, which are an attempt to introduce monadic constructs within a syntax more palatable to programmers with an imperative background. Effect systems are an alternative way of describing side effects as types. See also Arrows in functional programming — whereas monads generalize the results of a computation to effects, arrows further generalize the inputs similarly. Monad transformers — which allow monads to be composed in a modular and convenient way. Inversion of control — the abstract principle of calling specific functions from a reusable software entity. Uniqueness types - an alternative way of dealing with side-effects in functional languages References External links Haskell monad tutorials Monad Tutorials Timeline Probably the most comprehensive collection of links to monad tutorials, ordered by date. A (hopefully) painless introduction to monads What the hell are Monads? You Could Have Invented Monads! (And Maybe You Already Have. ), a gentle introduction. All About Monads Monads as Computation Monads as Containers Monads for the Working Haskell Programmer The Haskell Programmer's Guide to the IO Monad — Don't Panic Introduction to Haskell, Part 3: Monads On Monads A discussion of monads in Haskell, at the WikiWikiWeb site. Monads A monad tutorial providing examples of non-trivial monads apart from the conventional IO/Maybe/List/State monads. Understanding Haskell Monads Other documentation A tour of the Haskell Monad functions by Henk-Jan van Tuyl Notions of Computation and Monads by Eugenio Moggi, the original paper suggesting use of monads for programming "Monads for Functional Programming" by Philip Wadler, describing monads in Haskell (before they were implemented) Monads in languages other than Haskell Monads in Ruby Monads in Python Monads in Scala Monads in Clojure Monads in JavaScript Monads in C#
- On se place dans le cadre de la programation fonctionnelle typée. Un type monadique <math>M(t)</math> dérivé d'un type <math>t</math> est la donnée de une fonction <math>return : t \rightarrow M(t)</math> qui construit une monade de type <math>M(t)</math> à partir de n'importe quel objet de type <math>t</math>; une fonction <math>>>= : M(t) \rightarrow (t\rightarrow M) \rightarrow M(t)</math> qui permet d'appliquer une fonction <math>f: t\rightarrow M(t)</math> à une monade de type <math>M(t)</math>. En composant la fonction >>= (dite fonction de liaison) avec la fonction <math>return</math>, on peut appliquer n'importe quelle fonction <math>g:t\rightarrow t</math> à une monade de type <math>M(t)</math>. En ce sens une monade de type M(t) est un objet qui dérive du type t. L'utilisation la plus simple des monades consiste à encapsuler un objet de type existant dans un objet portant plus d'information. Par exemple en langage Haskell, une monade de type <math>Maybe(t)</math> est ou bien un objet de type t normal, ou bien la valeur <math>Nothing</math>. Cela permet de traiter de façon élégante les opérations interdites comme les divisions par zéro : int / int vaut ainsi un Maybe(int). Une autre utilisation fondamentale des monades est la gestion des entrées/sorties dans un programme Purement fonctionnel, c'est-à-dire sans effets de bord. C'est le cas de la monade <math>IO(t)</math> en Haskell, qui représente un programme impératif sans paramètre et renvoyant une valeur de type t. Ainsi getLine est une monade de type <math>IO(String)</math>, un programme impératif qui lorsqu'il est exécuté renvoie une chaîne de caractères (celle tapée au clavier). Confirmons qu'un programme impératif renvoyant un t est une monade. A tout objet <math>o</math> de type <math>t</math> on peut associer le programme trivial <math>return \; o</math> qui renvoie toujours <math>o</math>. C'est d'ailleurs l'origine de la notation <math>return</math> pour les types monadiques. Ensuite étant donné une fonction g:t->t il est naturel de pouvoir l'appliquer à un programme qui renvoie un t, cela donne un autre programme qui renvoie un t. On peut voir cette opération comme la concaténation du code source du premier programme et du code de la fonction g. La programmation fonctionnelle contourne ainsi le problème des entrées/sorties (naturellement des effets de bords) par la manipulation de ces programmes impératifs eux-mêmes et non des valeurs qu'ils retournent. Pour se fixer les idées, on peut se dire qu'une monade de type IO(int) est le code C d'un programme renvoyant un entier. Ainsi le type IO(int) est complètement légitime dans le cadre fonctionnel puisque que c'est simplement du texte. Lors de la compilation du programme fonctionnel, ces monades seront traduites en du code binaire qui aura bien l'effet attendu lorsqu'il sera exécuté par la machine. En particulier le main en Haskell est toujours de type IO(void).
- Una monade è una struttura dati con uno stato associato. Tipicamente è utilizzata per modellare un aspetto del mondo esterno al programma e permette ai linguaggi funzionali di rimanere puri, cioè senza effetti collaterali. Una monade incapsula lo stato dell'ambiente esterno e viene passata come parametro alle operazioni che hanno bisogno di conservare uno stato (un analizzatore sintattico, per esempio). Le monadi sono notoriamente utilizzate nel linguaggio di programmazione Haskell per le operazioni di input/output. Nell'Haskell, la funzione principale, il main, è una monade: *Main> :t main main :: IO Quindi il suo tipo è IO. Allo stesso modo, tutte le funzioni che fanno input/output sono monadi: *Main> :t putStr putStr :: String -> IO putStr prende una stringa come parametro e restituisce una monade, essa è quindi anche una funzione di ordine superiore (cioè una funzione che prende come input o restituisce come output un'altra funzione).
- 計算機科学におけるモナドとは、関数型言語において参照透過性を維持しつつ手続き型的な記述を行なうための枠組みを言う。主にプログラミング言語Haskellで用いられる。 元来はI/O等の副作用を伴う処理や、順序処理を自然に記述するために導入された。後に様々な領域でモナド形式による表現の有用性が発見され、現在では「モナド化」はHaskellプログラミング全般に強力な理論基盤を与えている。 モナドの名称は、圏論のモナド(モノイド+トライアド)に基づいており、ライプニッツのモナド(単子論)とは無関係である。
- Монада в программировании — это абстракция линейной цепочки связанных вычислений. Монады обильно применяются в языке Хаскелл. Она описывается полиморфным контейнерным типом с одним параметром, стратегией «поднятия» значения в монаду и стратегией связывания двух вычислений, второе из которых зависит от параметра, вычисляемого первым: m :: * -> * return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b В языке Хаскелл к этим операциям добавляется также fail :: String -> m a Эта операция не имеет отношения к теоретической сущности монад, однако используется в случае ошибки сопоставления с образцом внутри монадического кода. В частности, к монадам относятся: IO (монада строго последовательных вычислений): стратегия связывания — «сначала первое вычисление, затем второе» Maybe (монада вычислений с отсутствующими значениями): стратегия связывания — «если первое вычисление дало результат, то второе; иначе — отсутствие результата» List (монада вычислений с несколькими результатами): стратегия связывания — «все возможные результаты второго вычисления, применененного к каждому из вычисленных первым значений параметра» State (монада вычислений с переменной состояния): стратегия связывания — «начать второе вычисление с состоянием, измененным в результате первого» И некоторые другие. Монады также применяются для синтаксического анализа, продолжений (continuations), вероятностных вычислений и в других случаях. Концепция монад в программировании была унаследована из теории категорий: Монада (математика)
- Деякі із функціональних мов програмування використовують монади для структурування програм, що містять операції, що мають виконуватись в певному порядку. Назва монада походить із теорії категорій, розділу математики що описує шаблони, що можуть застосовуватись до різних розділів математики. Основними застосуваннями монадів в функціональному програмуванні є визначення операцій вводу/виводу (I/O) та зміни в станах без використання засобів мов програмування що чинять побічні ефекти . Принцип дії монадів полягає в тому, що, хоча функція і не може робити побічний ефект напряму, вона може створювати значення, що описує бажаний побічний ефект, і яке можна використати коли потрібно. Однак, I/O та керування станом в жодному разі не є єдиними способами використання монадів. Вони корисні тоді, коли розробник бажає описати обчислення в чисто функціональному стилі, виконуючи паралельно інші обчислення. Мова програмування Хаскель є функціональною мовою програмування, що інтенсивно використовує монади, та має синтаксичні конструкції для полегшення роботи з монадами.
- 单子(monad,也译单体)是函数式编程中的一种抽象数据类型,其特别之处在于,它是用来表示计算而不是数据的。在以函数式风格编写的程序中,单子可以用来组织包含有序操作的过程,或者用来定义任意的控制流(比如处理并发、异常、延续)。 单子的构造包括定义两个操作bind和return,还有一个必须满足若干性质的类型构造器M。
|