This action might not be possible to undo. Are you sure you want to continue?

BooksAudiobooksComicsSheet Music### Categories

### Categories

### Categories

Editors' Picks Books

Hand-picked favorites from

our editors

our editors

Editors' Picks Audiobooks

Hand-picked favorites from

our editors

our editors

Editors' Picks Comics

Hand-picked favorites from

our editors

our editors

Editors' Picks Sheet Music

Hand-picked favorites from

our editors

our editors

Top Books

What's trending, bestsellers,

award-winners & more

award-winners & more

Top Audiobooks

What's trending, bestsellers,

award-winners & more

award-winners & more

Top Comics

What's trending, bestsellers,

award-winners & more

award-winners & more

Top Sheet Music

What's trending, bestsellers,

award-winners & more

award-winners & more

Welcome to Scribd! Start your free trial and access books, documents and more.Find out more

From http://spbhug.folding-maps.org/wiki/MonadsEn

Introduction

The word "monad" is familiar to virtually everyone who has dealt with functional programming. Many people are scared away by their seeming abstractness and mathematicity and by the need to use them for the most simple tasks, like console I/O. The Internet is filled with monad tutorials and there is even a popular belief that one has the right to be considered an FP newbie no sooner than he writes such a tutorial. These articles present monads from different points of view: from the one of their underlying mathematical concepts, or like a 'hack' into the imperative world, or from a purely practical point of view, or extremely broadly and comprehensively. The text you are reading is meant to illuminate them from another one: monads will be presented as a generalization of certain common idioms and as a method for abstracting them.

**Goal and target audience
**

It is assumed that the reader is familiar with basics of Haskell and with the methodology of FP in general. Otherwise, one can get the required knowledge from articles listed at the end of this article. My goal is to explain the concept and give an intuitive understanding of monads with several examples, some of which are common and familiar and some are not. This text is not a practical manual on usage of standard monads.

**Three familiar examples
**

Here we consider three common idioms: sequential computations, computations with handling of absent values and computations that return a set of possible results. Then we shall point out their commonality.

**Sequential computations (the IO monad)
**

Consider the ';' operation, which means 'and then':

(print "Hello") ; (print "Goodbye")

This line means: Display "Hello" and then display "Goodbye". The execution of this program proceeds as follows:

At moment t0 the screen is blank At moment t1 the screen is modified by print "Hello"; the screen contains 'Hello'. At moment t2 the screen is modified by print "Goodbye"; the screen contains 'Hello Goodbye'

**Let us write this sequence as a system of simultaneous equations:
**

world(t=0) = (empty screen) world(t=1) = world(t=0) + (print "Hello") world(t=2) = world(t=1) + (print "Goodbye")

This way of programming (expressing the solution of a problem via a sequence of actions) is the most well-known and used one in main-stream languages: C, Java etc. One can easily see that in the world of imperative computations, I/O etc. all such systems of equations look like a 'chain': world(n+1) = world(n) + action. One can not take an old state of the world out of one's pocket and perform an action on it, because two different states of the world cannot coexist. Thus, an equation like world(10) = world(3) + (print "Hello") is impossible. So, a sequence of actions A1; A2; A3; ... can be viewed as A1 `then` (A2 `then` A3 `then` ...). The then operation suffices for describing a sequence of actions (it is actually the same as a semicolon, ;, but we are not used to seeing the semicolon as a binary operation). Note that the operation is associative (t.i., ((A1 `then` A2) `then` A3) == (A1 `then` (A2 `then` A3))), so the parentheses can be omitted; all languages do so. However, for a better intuitive understanding ('do the first action, then do the rest') one should interpret the `then` operation as right-associative. Now, a question arises: what should be considered the value of (A `then` B): the value of A, the value of B or something else? The traditional and logical way is to take the value of B. Really, if we had to first evaluate A and then evaluate B, that means that correctness of evaluation of B did depend on evaluation of A: for example, in the sequence

(send query to database) `then` (await answer from database)

the correctness of 'await answer' depends on whether 'send query' was evaluated. Thus, if we are interested in the correctness of B, we are interested in its value, at least in the cases where we are evaluating (A `then` B) to get some value and not just for the side-effects. From a purely functional point of view (where one considers that the only important thing about a computation is its value) one could say that the `then` operation is unneeded; then in the example above we could just write 'await answer from database'. But this is obviously false: we should first completely evaluate 'send query' and only afterwards start evaluating 'await answer'. This necessity is dictated by the pure fact that both computations have side effects, t.i. interact with the outer world. Morale: In the world of computations with side effects (I/O, modifications of variables) computations are bound with a 'and then' operation, which means 'do the first, and, only after it completes, do the rest'.

Computations with absent values (Maybe monad)

based on procedures 'list lines of a file' and 'list words of a line' the procedure 'list files in a directory and its subdirectories'. Morale: In the world where computations sometimes fail. null is returned. If an error occurs at any stage. String value = ourDatabase. This example can be easily generalized to a more sensible way of handling errors.null. if successful.get(key). computations are bound with the 'and then.? value = ourDatabase. if(f == null) return null.txt").Consider a synthetic but typical and familiar example: A program opens a file. where instead of null one uses values of an Exception type. which computes the total cost of all orders. if error E occurred. . The example shows a particular case where there is only one type of error . if(keys == null) return null. However. File f = open("keys. via a combination of such multiple-valued computations: the procedure 'get all orders of all departments of all shops'. and error in an intermediate computation causes the error in the whole computation. like 'list files in a directory' or 'split string into a list of symbols'.get(key) . Computations with many results (List monad) Consider computations that return a list of values. do rest. They can return them either directly. String key = readLine(f).? key = readLine(f) . which means 'do first and. assembling its result from results of recursive calls.? "The value is: " + value. return "The value is: " + value. if successful' operation. if successful'): File f String String return = open("keys. return error E'. Now let us substitute the .txt") . Here is a typical implementation of the first procedure. reads a line from it and searches a database for the corresponding value. the essence remains: functions return values of two kinds: 'results' and 'error signals'. based on procedures 'list shops'.? ('and then. 'list departments of a shop' and 'list orders in a department' the procedure 'get all words in a file'. if(value == null) return null. ('and then') operation for . or indirectly.

You will get a good understanding after two other examples of monads. let us continue. for each result' operation.* return [file]++[rec]. don't proceed to that section before reading the text in between Now. that's the precise reason why many people don't understand monads or consider them too simple.getCost(d)'.addAll(listFilesRec(sub)). which threads the next operation through all results of the previous one. listFilesRec(File file) { List<File> res. it is important to know that. for example.* Department d = getDepartments(s) .* rec = listFilesRec(contents) .getCost(). although these three monads are very often used for illustrating the concept. too complex or too useless. namely Parser and especially Dist. which means.add(file). they are the most easy and maybe even degenerate ones. computations are bound by the 'and. } } } Now let's consider the case where the number of levels of iteration is unknown: for example. 'for each result ord of getOrders(d) evaluate sum += ord. foreach(File sub : getContents(file)) { res.* operation. Warning At this point. } return res. What's in common? . res. understanding of just them does not give an understanding of monads in general.* sum += ord.getCost(). listFilesRec(File file) { contents = getContents(file) . recursively listing a directory. In my opinion. } Morale: In the world of iterations and non-determinate computations.* Order ord = getOrders(d) . which are described somewhat below. Shop s = getShops() . } Let us now rewrite these examples using a .foreach(Shop s : getShops()) { foreach(Department d : getDepartments(s)) { foreach(Order ord : getOrders(d)) { sum += ord. However.

whereas the second does (mainstream languages and languages without lazy evaluation tend to ignore this distinction. For example. So. So far. These dependencies should be managed not by the computations but by the implementation of (>>=) in the monad. -> b 4. computing "Hello" as "He"++"llo" is obviously radically different from reading "Hello" from keyboard: the first way doesn't have side effects. This can be interpreted as 'A value computed in a particular way'. for example 'A value computed with side effects' (IO monad) or 'A value that maybe hasn't been computed because of an error' (Maybe monad) or 'A value with multiple alternatives' (List monad). 1.. The second computation depends on the first. The result of this operation is the result of the second computation.. b . . depending on a 'parameter' computed by the first. we overloaded the . this is the precise mission of (>>=). where a is the first computation and (a > b) is the second. For example.i.* works in absolutely the same way. This is the final and correct variant. The print function doesn't care about how the displayed string was computed. the 'first' one and the 'rest' one. Note again the polymorphism: the type will be of form forall a. b . to use this as a means of abstraction. namely (>>=). (a type expression depending on a and b) 3. and it doesn't deserve such a loud name as 'a monad').. This is a polymorphic operation: its logic does not depend on the values and types of values it binds. Let us formalize the concept of 'binding' two computations. However. otherwise we wouldn't need any shiny monads and could just perform the second computation. we'll have to formalize this concept. readLine has type IO String instead of String and a hypothetical lookupUserByName function has type String -> Maybe User instead of String -> User. and it is flip ($). A monad attaches an adjective to all values. t. whether it binds a list of shops with a computation depending on a shop or when it binds a list of files with a computation depending on a file. Now. there is an important caveat: a value is radically different from the same value computed inside a monad! For example. forall a.? and . So.. This is even closer. The type of (>>=) obviously depends on the types of the first and second (rest) computations: it will have at least 2 type variables: a (type of the first computation) and b (type of the second computation). we get something like a -> (a -> b) -> b. but we won't). operator. Now. we get something like m a -> (m a -> m b) -> m b. 2.An attentive reader might have already noticed that in all cases we chose a specific strategy of binding two computations. the reverse application function. but the second computation actually doesn't need to know about the fact that its argument is 'wrapped'.* operations to one operation. One can say that this is the precise essence of monads. . generalize the . the type of a computation in a monad m is not 'a' but 'm a'. . This is close to true (although there is surely something wrong with it: there exist only one function with such a type. This type can be read as follows: (>>=) in a monad m binds monadic computation of a . whereas getContents doesn't care that it is actually called on several files and that its results are concatenated. we get the type (>>=) :: m a -> (a -> m b) -> m b.

. So. If we perform the 'monadic computation of a parameter' using return.. their meaning will be clear from their definitions. which are less obvious. since such an operation must.) one can re-formulate this law as follows: z = ( y = x . directly or indirectly.*. It may seem that there is no need to have such an operation. return (f y ) . (let us denote them all with . and for a concrete case. return converts a value to what we would get if the value was computed inside the monad. as if it were the successful result of a computation that potentially could fail' . exist in any useful monad. It's easy to check that for the monads considered above such implementations (return "Hello" = ["Hello"] etc.parameter (m a) with a monadic computation depending on this parameter (a -> m b). a way to create a monadic value usually exists: there's nothing difficult about creating a list of values (a value of type List a).. it makes sense to include it into the definition of a monad. as monolithic and to not care about placement of parentheses. the List monad. as if it were the sole result of a multiplevalued computation' . . and in the List monad return "Hello" = ["Hello"] . in the IO monad return "Hello" :: IO String and this computation represents 'the string "Hello".. . This law allows to interpret the sequence a . This is the first of the three monad laws. This operation is called 'return' and has type a -> m a. For example. return "Hello" = Just "Hello" and it means 'the string "Hello". c . 'the string "Hello".. Remember that (>>=) in the monad m binds monadic computation of a parameter with a monadic computation depending on this parameter. b . In the Maybe monad. as if it was computed with side-effects' . Things will become more clear soon. It takes an arbitrary fixed value and 'lifts' it into the monad. return (g z) . However. Now we are able to bind two monadic computations together. In terms of operations like .) satisfy this law. yielding a monadic result (m b). but there is no way to create a monadic computation 'from nothing' for an arbitrary monad. . here are the three monad laws: Monad laws Agreement of return and (>>=): (return x >>= f) == (f x) Associativity of (>>=) : ((x >>= f) >>= g) == (x >>= (\y -> (f y >>= g))). There are another two laws. attaching the monad's adjective to it. for instance. it would make sense to require the effect to be the same as if the parameter was simply passed to the second computation: (return x >>= f) == (f x).?. The reasoning behind such a choice of implementing return are intuitively clear but now we'll see their theoretical grounding. because we will always use a concrete monad (Further we'll see that this isn't true and there exist useful functions that work for all monads).

return (g z) ) Right unit: (x >>= return) = x . >>=). binding a monadic computation x with a parametrized computation which simply returns the parameter is the same as just x. the Monad class in Prelude contains one more member: fail :: String -> m a but we won't talk about it because it has no relation to the concept of monads and in the next version of Haskell standard it is planned to move this function to a separate class. to which corresponds the adjective 'ordinary': Identity String is 'just an ordinary String'.is identical to y = x . This monad essentially doesn't change neither types of values. Standard monads Identity This is the simplest monad. that is. One can rewrite this law as (x >>= (\a > return a)) = x. b . Now we can give a complete definition of a monad: Definition of a monad A monad is a triple (m. m a -> (a -> m b) -> m b These requirements can be formalized at the type system level. nor the binding strategy. ( z = (f y) . return.. where: m is a type with one argument return :: forall a .. and Prelude contains a class definition: class Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b A monad should satisfy the laws (they can't be enforced or checked by the compiler but their violation will most probably lead to exotic consequences): (return x) >>= f = f x (x >>= f) >>= g = x >>= (\y -> f y >>= g) (x >>= return) = x Actually. data Identity a = Identity a return a = Identity a . a -> m a (>>=) :: forall a.

(Identity a) >>= f = f a It is not clear why one would need such a monad. For example. If one value depends on another. So. data Maybe a = Nothing | Just a The implementation is trivial: binding a 'just' value with a parametrized computation is simply passing the parameter to it. "c:/work/documents"] State (the monad of computations with a mutable state) This is a more complex monad not mentioned above. It corresponds to a computation that has an internal state modified while it proceeds. they are beyond the scope of this article. depending on a parameter Thus. "c:/musi c/Beethoven". "c:/work/projects". alternatives of both are enumerated. or 'an indeterminate value' is an 'indeterminate' function that returns a bunch of possible results. but the state is not as global as in the IO monad (where . Maybe (the monad of computations with handling of absent values) In this monad there are two kinds of values: 'ordinary' ones and a special value 'the value is missing'. however. return a = Just a Nothing >>= f = Nothing (Just a) >>= f = f a List (the monad of computations with multiple results) Here each value has several 'alternatives'. "c:/music/Rammstein". let us consider this monad a purely illustrative degenerate example. return a = [a] params >>= f = concat [f x | x <. whereas binding a missing parameter with a parametrized computation yields a missing result. as expected. one might have ["c:/music". but it has applications with monad transformers. "c:/work"] >>= getDirectoryContents = ["c:/music/Bach". params >>= f :: [b] is a list of possible results obtained by applying the function to possible arguments.params] Let us remember the types participating: params :: [a] f :: a -> [b] is a list of values.

.a computation potentially changes state of the whole world and where the state can't be obtained directly or stored). we could do it in a boilerplate fashion: rand :: State RndGen Int rand = State $ \(RndGen x) -> (x.Let us omit the implementation for now. they are called get and put and the State monad in Haskell is actually equipped with them: rand = get >>= \(RndGen x) -> put $ RndGen ((x*1367823 + 918237) `mod` 32768) >>= return x This code is a bit longer but it doesn't look like a mystical lambda abstraction. It is not beautiful but somewhat later we'll see that Haskell has syntactic sugar for this kind of code. RndGen ((x*1367823 + 918237) `mod` 32768)) However.. returns a new state). It will need a stateful random number generator.i. The get and put functions are not hacks. -. it seems more natural to equip the State monad with functions for reading and changing state. Here each computation does two things: it returns a value and modifies the state (t. it will be shown below. s)} (probably it would better be called StatefulComputation but that's somewhat too long). That's exactly the type of the State monad: newtype State s a = State {runState :: s -> (a. a computation of type a with a state of type s has type s -> (a. they are implemented rather trivially but it is instructive to have a look at them: get :: State s s . instead it manipulates state in an obvious way. a program implementing the Monte-Carlo method.. So. Consider. monteCarlo :: (Int -> Bool) -> Int -> State RndGen Int monteCarlo experiment 0 = return 0 monteCarlo experiment n = rand >>= \r -> if (experiment r) then monteCarlo experiment (n-1) >>= \s -> return (s+1) else monteCarlo experiment (n-1) Note that the code of monteCarlo has no signs of presence of assignment and change of state: the code is written in a purely functional style and its statefulness is hidden by the State monad and the rand function. for instance. How would we implement rand? Well. This program will use a function 'generate a random number' that returns a new random number and changes the generator state: rand :: State RndGen Int rand = .s).

finalState) where (res1. Let us take a naive approach to describing IO: . s) put :: s -> State s () put s' = State $ \s -> ((). finalState) where (res1. However. it is also much more peculiar. whereas pure computations involved proceed lazily as usual because their order doesn't matter. finalState) = (p res1) intermediateState -.5] IO's adjective is 'computed with side-effects'. s) -. the correct way is more complex than the intended complexity of this article. finalState) = r2 intermediateState -.Perform the first computation. using the parameter (res2.p :: a -> State s b = a -> State (s -> (b.*Compute* the second computation. you can look at it in [C. then side effects of the second one' (remember the example with sending query to a database and waiting for response). s)) is a stateful computation of 'a' -.Perform the second computation This code can be made clearer if we remove the State constructor (however. compute the parameter (State r2) = p res1 -. intermediateState) = r1 s -. s)) is a stateful computation of 'b' parameterized by r1 (State r1) >>= p = State passState where passState s = (res2.get = State $ \s -> (s.r1 :: State s a = State (s -> (a. and its strategy of binding two computations is 'first perform side effects of the first one. it will become incorrect): r1 >>= p = passState where passState s = (res2. intermediateState) = r1 s -. s') It turns out that get is 'a stateful computation that just returns the state' and put is 'a stateful computation that returns nothing in particular and just modifies the state' Now look at the implementation of the State monad itself: instance Monad (State s) where return a = State dontChangeStateAndReturnA where dontChangeStateAndReturnA s = (a. compute the parameter (res2.Perform the first computation.Compute and perform the second computation IO (the monad of computations with side-effects) This section presents the IO monad in a perhaps intuitively understandable but incorrect way.

and. which get much worse because of Haskell's lazy evaluation mechanism: now it is very hard to say when exactly will an effectful computation be performed and whether it will be performed at all. reading a global configuration file). It is difficult to explain how exactly (*) is achieved. transformation of which leads to the computer performing observable effects).unsafePerformIO with type IO a -> a.. debug output) or when it is always the same. the computation is idempotent (for example.. Having done that. The only way to construct a sound model of sequential computation is to prohibit saving the world's state for later use and breaking the linearity. shows the most important properties of the IO monad: the fact that pure functional computations get unchanged and that effectful computations get sequenced. Usage of unsafePerformIO can be reasonably safe only in cases where its side-effect does not affect anything (for example. But even in this cases. this fact is enforced by the typechecker! This is one of the reasons for low bug count in Haskell problems because it eliminates one of the most frequent causes of bugs: indirect interactions because of side effects. presenting an IO value as a chunk of code that.IO..Unsafe.'. see later Remember that in the beginning of this text. Others .. -> IO . and the fact that one can't get out of the IO monad and hide the effectfulness of a computation.. it's better to avoid it. and presenting it as a function from a bunch of (already performed) effects to a bunch of some more effects. we can be sure that it has no side effects. -> IO ... However. side effects present" and vice versa: if a function does not return an IO value. Some ways of implementing the IO monad include presenting it as a State monad which has the whole world as its state (or some internal runtime state. like processor registers. with this approach (data IO a = IO a) it is completely impossible.. This forces sequencing of effects because the function can't proceed before its 'input' effects are performed. To do this. a function that uses side effects gets itself annotated with "warning. t.i.data IO a = IO a return a = IO a (IO a) >>= f = f a -. it suffices to hide the IO constructor and thus prohibit pattern matching: let (IO s) = readLine in . To be honest. we told that there's no way to restore a previous state of the world and that the essence of sequential computations is to build a strictly linear chain of world states. because with this function we also obtain all the imperative problems of hidden effects. when ran. there exists a function System.. I/O ports and process memory. Thus. performs an effect.. then the type of this function will also be '. but one should think twice before even considering its usage. If a function uses a value of type .(*) but with side effects of 'a' magically performed before applying 'f'. together with (*) and hiding the IO data constructor. we now have a stunning property: there's no way out of the IO monad! There is no way to convert IO a to just a and no way to hide the fact that a computation has side effects... this approach.

* operator shouldn't be interpreted literally. Code with the .getCost(). So. Let us rewrite it in Haskell: let s = d = ord in sum getShops getDepartments s = getOrders d (getCost ord) This code is of course incorrect: it doesn't typecheck. s has type [Shop]. do syntax Consider again the example with multiple-valued functions (the List monad): Shop s = getShops() . called 'do syntax': . this code means not 'Let s equal getShops' but instead 'Let parameter s be computed via getShops'.Haskell's standard library defines some more monads: Reader. similarly for d/getOrders and ord/getCost. so getDepartments can't be applied to s.getCost(). Writer and Cont. s has type [Shop] but the rest of the computation depends on Shop.* sum += ord. Actually. I recommended to look at them yourself: Reader and Writer are conceptually simple and often used.* we meant that s is a parameter used by the rest of the computation.* Department d = getDepartments(s) . has type [a] -> (a -> [b]) > [b] and. Its discussion is beyond the scope of this article.* Order ord = getOrders(d) . Results of this computation will be used by . in case of the List monad. In haskell: sum (getShops >>= \s -> getDepartments s >>= \d -> getOrders d >>= \ord -> return (getCost ord)) Obviously.* that. in the particular case where a = Shop. when writing Shop s = getShops . Taking this into account we can rewrite the first fragment: getShops() >>= \s -> getDepartments(s) >>= \d -> getOrders(d) >>= \ord -> sum += ord. So. not Shop. Cont is a complicated monad used for programming in 'continuation-passing style'. [Shop] -> (Shop -> [b]) -> [b]. such a kind of 'assignment' corresponds to the syntactic idiom value >>= \variable -> . Haskell has syntactic sugar for that.

For example. The real power of monads is disclosed when one finds out that a specific problem domain is well described in terms of monads.getShops d <..readNumber putStrLn "Input another number" b <.. especially in case of the IO monad: main = do putStrLn "Input a number" a <. Syntactic analysis Let's design a parsing library. for example: .).. of course. but it they were all that monads are about. Somewhat later we'll return to such actions and monads. Of the monads mentioned above. Such syntax makes the code look more imperative. a number parser will return numbers. of some practical value and they do illustrate the idea of monads. This is how the code above gets translated: main = putStrLn “Input a number” >>= \_ -> readNumber >>= \a -> putStrLn “Input another number” >>= \_ -> readNumber >>= \b -> putStrLn $ “Their sum is: ” ++ show (a + b) Designing monads The three monads above are.getDepartments s ord <. A number parser will return Nothing when instructed to parse "Hello". monads couldn't be called that useful and interesting. Let a parser be parametrized by type of the values it returns. Now we'll look at two such examples.getOrders d return (getCost ord)) This gets translated to precisely the code above. only IO and State have computations whose return value is not important. Having such a type. gets translated as if it was written not putStrLn "Input a number" but _ <putStrLn "Input a number": the computation is performed but its result is not used (is passed to a constant function \_ -> .sum (do s <.readNumber putStrLn $ "Their sum is: " ++ show (a + b) Inside a do block a sequence of two lines where the first one is not a binding of the form a <. and these examples could be implemented in some different way. Type of a parser will be like type Parser a = String -> Maybe a.. one can easily write some 'primitive' parsers. where the Maybe indicates that parsing may sometimes fail. whereas a code parser will return the code's syntax tree.

a parser for numbers a parser that always returns the same constant value a parser that always returns the input string a parser that always fails a parser that expects a particular string. s'') -> return (va. which does not use the Maybe monad at all: the (>>=) and return functions are expanded: a <*> b = \s -> case (a s) of Nothing -> Nothing Just (va. returns () if it is found and fails otherwise One can also implement the <|> combinator: parallel composition of parsers: it tries to apply the first parser and. s') <. That's because the combinator knows nothing about the implementation of its arguments and it has to check all possible partitions of the input string into two.b) a <*> b = \s -> do (va. for example.s') -> . This is extremely slow and. call the first parser on the left part and the second parser on the right part. in case of more than two parsers. for a better understanding look at two more variants having the same semantics: The first one: How the compiler expands the code above: a <*> b = \s -> (a s) >>= \(va. s') -> (b s') >>= \(vb. s') <. applies the second one instead.vb) This code fragment uses the Maybe monad and do-syntax. 456)) can't be implemented efficiently in this way. Now sequential composition is easy: (<*>) :: Parser a -> Parser b -> Parser (a. We have to take this fact in the Parser type: type Parser a = String -> Maybe (a. a parser for two numbers ("123 456" -> (123.a s (vb. Actually. (<|>) :: Parser a -> Parser a -> Parser a a <|> b = \s -> case (a s) of Just v -> Just v Nothing -> b s However we can't implement sequential composition (<*>). String).b s' return (va.vb) The second variant. if it fails. complexity becomes exponential in both length of the input string and parser count. we would like to implement sequential composition as follows: let the first parser 'eat' as much of the input string as it can and pass the rest to the second parser.

oneOrMore digit s2 (_. String)]. s2) <. s1) <. The easiest (or the only) way to implement it is to transition from the Maybe type to lists. Philip Wadler formulated this as 'Replace failure by a list of successes' in his work [C. It will be useful for parsing strings like this: Napoleon 1769|Emperor of France Henry the 8 th 1491|King of England. s5) <.oneOrMore anyChar s (_. Let us now consider a couple more important combinators: start with oneOrMore :: Parser a -> Parser [a].char '|' s3 (info. had 6 wives A recognizing parser (one that just checks correctness but doesn't return anything) can be implemented like kingInfo = (oneOrMore anyChar) <*> space <*> (oneOrMore digit) <*> char '|' <*> (oneOrMore anyChar)` Let us invent an implementation for oneOrMore: A greedy variant: oneOrMore p applies p while it is possible. String) it is easy to implement sequential parser composition and also (left as an exercise for the reader) parallel composition. s'') -> Just ((va. Implementations of various operations will become even simpler and the implementation of <*> with the do-syntax won't change at all! Now let us implement a better kingInfo that will not only check syntax but also return a King: data King = King {name::String. Only the second variant suits our needs.vb).1].case (b s') of Nothing -> Nothing Just (vb. s'') So. Obviously this won't work with this example because the very first oneOrMore anyChar will eat the whole string. birth::Int. info::String}: kingInfo = \s -> do (name. s5) We see a dependency between computations that hasn't been taken into account in the List monad: seems like we need our own! It will be a lot like the List monad but it will store the rest of the parsed string together with each parsed value: somewhat like a mixture of List and State: . s4) <.space s1 (birthStr.oneOrMore anyChar s4 return (King name (read birthStr) info. A non-deterministic variant: (oneOrMore p1) <*> p2 should find a way to split the input string into two. with a type type Parser a = String -> Maybe (a. where the first can be parsed by several applications of p1 and the second can be parsed by p2. s3) <. Now the parser will have type type Parser a = String > [(a.

Noticing monadic structure in a problem is very important and useful: usually. when it is possible. (vq.p s. normal and aggressive The traffic light has 3 positions: yellow.oneOrMore anyChar space birthStr <.s') <.3].6 and aggressive with a probability of 0.1 0. we exploited the 'monadic' essence of BNF and of the parsing process.3 . for example. normal with a probability of 0.s'') | (a. they collide with a probability of 0.1 0.newtype Parser a = Parser {runParser :: String -> [(a.q s'] and the 'royal' example can now be rewritten as kingInfo = do name <.2 0.1]): There are three types of drivers: cautious.s') <.pa s. The Parsec parser library uses a similar approach and its idea is taken from [C.oneOrMore anyChar return (King name (read birthStr) info) Now the parser declaration looks precisely as a Backus-Naur grammar.2.9 Red 0 0.s'') <. (b. to achieve this. Statistical distributions Now we'll do some statistic modeling.s)] pa >>= pb = Parser $ \s -> [(b.vq).3 A driver is cautious with probability of 0. each cell means ' This type of driver starts driving when he sees this traffic light with this probability' Cautious Normal Aggressive Green 1 1 1 Yellow 0.2 The following table describes reactions of various drivers to various traffic lights.oneOrMore digit char '|' info <. Let us model the behavior of three types of drivers on a crossroad and estimate their collision probability (example taken from [D.pb s'] During transition from Maybe to this monad all primitive parsers and their combinators undergo trivial changes. s'') | (vp. <*> now looks as (Parser p) <*> (Parser q) = Parser r where r s = concat [((vp. the code becomes as clear and beautiful as in this example. green and red If two 'perpendicular' drivers on a crossroad start driving simultaneously.String)]} instance Monad Parser where return a = Parser $ \s -> [(a. s'') <.

Light light) { Action firstAction = first. return result. Then.actionOn(light). Driver second. bool result = doActionsLeadToCollision(firstAction. 'bool' will become 'distribution over bool'. of what use can it be? One usually integrates it over an interval to obtain the probability of a value belonging to the interval. The answer to the first question depends on how we shall use these values. } The only thing we need to do in order to transform this simple procedure into a computation of collision probability is to replace every type T with 'a distribution over T': for example. For that we'll need: Domain of a value (its carrier. in a more general case.The goal is to estimate the collision probability between two given types of drivers and average it over all types. Let us forget for a moment about the statistical nature of the problem.actionOn(light). It makes sense to assume that we'll generate values and compute statistics over them. the problem will be solved. Action secondAction = second. or. the dispersion or expectation of some function of the value But dispersion can be expressed via the expectation: Dx = M[(x-Mx)2]. through which all others can be expressed: Carrier Generator Procedure for computing means . etc. but this integral can also be expressed via the mean: 'P{x0<x<x1} = M[if(x0<x<x1) then 1 else 0]'. In the infinite case we don't actually need the distribution function. secondAction). Of course. Really. if the language provides us with arithmetic over such types. the point is that for some practical computational purposes it is can not be used if specified directly as a computational procedure. To put it together. it would be silly to say that the distribution function is useless. Two questions arise: 1) What is a 'distribution over T' and how to represent it in our program and 2) How to implement arithmetic over such values. 'Driver' will become 'distribution over Driver'. or support) Probabilities of each value appearing (in the discrete case) or the distribution function (in the continuous case) A procedure of generating a value with such a distribution A way to compute the dispersion or mean of the value. Then the solution becomes a trivial deterministic procedure: bool collide(Driver first. it looks like we'll need three 'basis' properties. also probabilities of individual values in the finite case can be expressed as P{x=x0} = M[if(x==x0) then 1 else 0].

.i.. gen = \g -> let (a. a2...Random data Dist a = Dist { support :: [a]. Obviously.. StdGen). t. The randomization operator has type: (distribution of parameter p) -> (distribution depending on p) -> (randomized distribution). because for the general case of infinite distributions we'll be unable to implement the expectation function precisely. a3.). the following occurs: The carrier is assembled as a union of carriers of 'db' distribution across all possible values of the parameter. Addition can be generalized to an arbitrary function.i. is randomization. During randomization. if we replace 'distribution over a' with 'Dist a'. The distribution of their sum can be computed by randomization of a+b over the parameter a (randomization of a value over a parameter is averaging or obtaining of its distribution with a random value of the parameter). (>>=) :: Dist a -> (a -> Dist b) -> Dist b: here da is distribution of the parameter and fdb is a function depending on the parameter and returning a distribution db. expect :: (a -> Float) -> Float } Now.Let us consider only discrete distributions with a finite carrier.i. across values of 'support da'. or. what about the second question? Let us compute the sum of two fuzzy values: an integer a and an integer b. the distribution where the random value can have only one particular value with a probability of 1: instance Monad Dist where return a = Dist {support = [a]. t. return corresponds to the delta distribution. So. . for computing characteristics of expressions of the form f(a1. t. g). module Dist where import System. expect = \f -> f a} da >>= fdb = Dist { support = concat [support (fdb a) | a <. Dist a > (a -> Dist b) -> Dist b.support da]. the only operation needed for composing distributions from parts. the generator always generates a and the expectation of function f equals f(a). g') = (gen da g) in (gen (fdb a) g'). the number of function arguments can also be generalized to an arbitrary large value. gen :: StdGen -> (a. expect = \f -> expect da (\a -> expect (fdb a) f) } This is how these operations work: return a returns a distribution whose carrier is a singleton set of a. gen = \g -> (a. Whoa! This is precisely (>>=) :: m a -> (a -> m b) > m b applied to the Dist monad! That's true: statistical distributions form a monad that has randomization as its binding operator.

0 0.3 _ `collision` _ = prob 0.0) sg in (if x < p then (gen d1 sg') else (gen d2 sg')) e f = p * expect d1 f + (1-p) * expect d2 f prob p = choose p (return True) (return False) freqs [] = error "Empty cases list" freqs [(_. computes the 'db' distribution and uses it to generate the result Expectation uses the randomization formula: M.0 0.2 0. The generator generates a parameter. choose p d1 d2 = Dist {support = s..b)] = Ma[Mb[f(a.b)]] Now we can define a couple of easy distributions and proceed to solving the original problem.9 0.3 Drive `collision` Drive = prob 0. (0. (0. value).a)] = return a freqs ((w1. a)) as) mean d = expect d id disp d = expect d (\x -> (x-m)^2) where m = mean d probability f d = expect d (\x -> if f x then 1 else 0) This suffices for the original problem. Cautious). For illustrative purposes a single distribution.[f(a.6.2.1 0.0. which.1. gen = g. expect = e} where s = support d1 ++ support d2 g sg = let (x.1 0. data Light = Red | Green | Yellow data Driver = Cautious | Normal | Aggressive data Action = Drive | DontDrive drive p = choose p (return Drive) (return DontDrive) _ Cautious Normal Aggressive Cautious Normal Aggressive `actOn` `actOn` `actOn` `actOn` `actOn` `actOn` `actOn` Green Yellow Yellow Yellow Red Red Red = = = = = = = drive drive drive drive drive drive drive 1.d2 `actOn` light a1 `collision` a2 .sg') = randomR (0.d1 `actOn` light a2 <. which is determined by pairs (probability.b. will suffice.a) -> (w/(1-w1). Aggressive)] simulate d1 d2 light = do a1 <.a.2.a1):as) = choose w1 (return a1) (freqs $ map (\(w.0 driver = freqs [(0. Normal). freqs. in turn.. can be expressed with the choose combinator: 'a mixture of two distributions in proportion p : 1-p'.

driver d2 <..simulateOverDrivers light = do d1 <. Also. It's hard to call it an 'operation' but it nonetheless works the same way for all monads and is equally useful for all of them.foo :: m a -. m . the fact that we noticed a monad in the problem allowed us to express its solution very closely to the problem domain.. liftM :: (a -> b) -> (m a -> m b) liftM f ma = do a <. . Generic monadic computations and monad combinators We've seen several examples of problems that are well expressed in terms of monads: so. t..driver simulate d1 d2 light probCollisionOnRed = probability (==True) (simulateOverDrivers Red) probCollisionOfTwoAggressiveOnYellow = probability (==True) (simulate Aggressive Aggressive Yellow) Now. as a black box. once again.ma .i. However. this won't typecheck..foo b <. It is not obvious that such operations do exist at all and that they can be useful: all the monads we spoke about were completely different and served different purposes.f :: a -> b -> m c Why not write simply return (f foo bar)? Alas. our programs often contained code fragments like this one: do a <. But the sole terminology is not a big enough reason to introduce a new abstraction into the language.ma.bar return (f a b) -.mb. one of the advantages of monads is their terminology that allows to compactly describe certain problems and computation patterns. I'm talking about operations that serve the same purpose regardless of which monad they are applied to. b <.bar :: m b -. In order for an abstraction to be useful we need operations that actually use it as an abstraction. t. return (f a b) etc. operations polymorphic with respect to the monad type: op :: (Monad m) => . return (f a) liftM2 :: (a -> b -> c) -> m a -> m b -> m c liftM2 f ma mb = do a <. Simplest monadic combinators The first situation where we used different monads in the same way is the do-syntax.i.. they do. But this pattern occurs extremely frequently and it makes sense to abstract it..

) driver driver Now let us imagine that we are going to print a list of values: perform putStrLn for each value. But Haskell is a lazy language and elements of the list are not forced and remain unevaluated calls of putStrLn. Now we can write things like this: (this code fragment reads a string from the keyboard and returns it converted to upper case) readAndUpper :: IO String readAndUpper = liftM (map toUpper) getLine Or like this (in the Dist monad): twoDrivers :: Dist (Driver. this is not a solution.These functions liftM. a list of actions.Driver) twoDrivers = liftM2 (. we obtain the standard function sequence :: Monad m => [m a] -> m [a] and a similar function mapM :: Monad m => (a -> m b) -> [a] -> m [b] mapM f as = sequence (map f as) The standard library defines some more counterparts of list functions and control structures for monads: . It has no mention of the IO monad and is monadpolymorphic! Analogously. doIOs [] = return [] doIOs (a:as) = do a . Their somewhat obscure names mean 'lift function into monad. that is. Look at the types: values :: [String] putStrLn :: String -> IO () map putStrLn values :: [IO ()] So. to perform this list of actions we have to perform each of them in turn. doIOs as doIOs (map putStrLn values) If we start the interpreter and look at the type of doIOs. in Control. so that it operates not on simple values but on monadic values but does the same thing as before'. are implemented in the standard library. Now. we get a list of values of type IO (). liftM2 etc.Monad. the IO word should be removed from the name of the function. map putStrLn values Alas. we see that it is doIOs: (Monad m) => [m a] -> m [a].

i) | i <. Why do we need this genericity? It is not yet obvious what applications there are for the combinators described above (except for liftM) apart from structuring actions in the IO monad. right?). these computations would have a more senseful result than (). 2. For example. presence of effects should be interpreted as .. They seem to not perform any computations (if they would.4] Let us create a parser that parses 5 numbers separated by space: fiveNumbers = replicateM 5 ((zeroOrMore (char ' ')) >> readNumber) The functions that end in an underscore and return m () deserve special attention. the monad of 'computations with mutable world' they may be used in the similar State monad.0/fromInteger a.when :: Monad m => Bool -> m () -> m () when b m = if b then m else return () replicateM :: Monad m => Int -> m a -> m [a] foldM :: Monad m => (a -> b -> m a) -> a -> [b] -> m a and some more. 3 and 4 correspondingly: uniform a = freqs [(1. the monad of 'computations with mutable state' for the same purposes. where insert has type (Ord a) => State (BinaryTree a) () and BinaryTree is the type of balanced trees: (Ord a) => [a] -> BinaryTree a = s' = runState (mapM_ insert) emptyBinaryTree = do t <.uniform a return (s + da)) (return 0) [1. these functions should be used only with monads that have effects. Let's look at some examples: Apart from IO.a]] sumDist = foldM (\s a -> do da <.[1.get put (insertBinTree a t) return () collectDistinct :: collectDistinct as where (s'. _) insert a Let us generate distribution of the sum of 4 numbers uniformly distributed in intervals of 1 to 1.. to collect distinct elements of a list we can traverse it with mapM insert. These effects include not only side-effects of the IO monad. For the case where a computation is important solely for its side-effects but not the return value these operations have counterparts with an underscore: mapM_ :: Monad m => (a -> m b) -> [a] -> m () sequence_ :: Monad m => [m a] -> m () etc.

this functions will only use the presence or absence of a value but not the value itself. but one can say that the List and Maybe monads don't possess it. In this case it makes sense to make implement potentially failing operations as monad-polymorphic and use fail to report errors. the interpreter monad of some language may implement fail with printing the error stack trace. like IO. 3]. -. counting nodes satisfying a predicate. sequence_. 2. It's hard to imagine a situation where such use of the List monad would be intended. It makes sense to use a monadic action with an effectful monad. and will be dismissed. 3] was just thrown away and only its length was used. XML documents. a pure function won't fit because its result won't be included in the answer anyway. the sequence do [1. replicateM_ and their kin are useless. so it's better to use the SAX model (Simple API for XML. State and Parser do. Such programs often use tree traversing operations: printing the tree to screen. For example. baz).String)]} data Tree = Tree Node [Tree] data NodeEvent = Enter Node | Leave Node Then the traversal function will look like walk :: (NodeEvent -> action) -> Tree > result. However. analogously. 6. What can be used as an action? Of course. bar. But in a typical SAX implementation the handler doesn't return anything and all the handling and computation work falls on the shoulders of the handler. Actually. For the Maybe monad. it won't get any information on the tree structure. 6. in this monad the functions mapM_. Now let us consider a less trivial example where we'll create our own monad-polymorphic combinator and touch the topic of monad transformers.Tree datatype data Node = Node {tag :: String. [5.(sensibility of sequences like do foo. 5. whereas IO. For instance. it's hard to imagine where usage of Maybe in such a situation would be preferable to a simple Bool. supported by most of contemporary XML parsers) and feed the handler with subtree entry and exit events. . attributes :: [(String. thus. if the action will be given only the node content. We'll follow this way: walk :: (NodeEvent -> actionWithoutResult) -> Tree -> noResult. 6] does not make sense: its result is [5.sensibility of the >> operator and of do without <. serialization to a stream. 6] but the value [1. 2. in most cases monad-polymorphic combinators either implement an 'imperative' traversal of some structure or use the monad's implementation of fail for custom error handling. State etc. 5. An example: SAX Assume that we are writing a program for processing some tree structures: for example. getting a list of all nodes or computing an aggregate function of these nodes. Most probably we'll need a function that traverses the tree and performs some action on each node. Seems like this property is impossible to express formally.

Thus. Let us proceed to the implementation: walk :: (Monad m) => (NodeEvent -> m a) -> Tree -> m () walk f (Tree n ts) = do f (Enter n) mapM_ (walk f) ts f (Leave n) return () Now let us use this function to implement indented pretty-printing the tree to XML. i) -.ats] ++">" . performing a monadic action for each entry or exit event.Prints a line with indent justIO $ putStrLn (replicate i ' ' ++ s) Now we can use these functions to solve the original problem: -. return (i. Printing indented text has two aspects: There are side effects.v) <.i. we get walk :: Monad m => (NodeEvent -> m ()) -> Tree -> m (). Let us implement our own simple monad. the monad of 'indented output': newtype IndentIO a = IndentIO { runWithIndent :: Int -> IO (Int. performs an action with side-effects and returns the new indent level.()) -.Decreases indent without performing any action getIndent = IndentIO $ \i -> return (i. a) (IndentIO r) >>= f = IndentIO r' where r' i = do (i'. Here are some functions that we'll definitely need: justIO action = IndentIO $ \i -> do action .Returns the current indent without performing any action printIndent s = do i <. ()) -. namely the current indent level The first aspect forces us to use the IO monad while the second one makes us think og State. a) } instance Monad IndentIO where return a = IndentIO $ \i -> return (i. a) <.getIndent -. t.r i runWithIndent (f a) i' In this monad a value is a function that receives the current indent level.Performs an action without changing the indent indentMore = IndentIO $ \i -> return (i+4. ()) -. but neither monad fits by its own. we'll have to use the IO monad There is a mutable state passed around.Generates a string of the form <tag atr1="v1" atr2="v2"> showEnter (Node tag ats) = "<"++tag++ concat[" "++n++"=\""++v++"\"" | (n. which traverses the tree inside an effectful monad m.Increases indent without performing any action indentLess = IndentIO $ \i -> return (i-4. The implementation is very similar to implementation of State but passing the state occurs inside the IO monad.

. we've missed another interesting topic: the theoretic grounding for the conception of monads and their formulation in terms of category theory. the example with IndentIO is a good illustration of how monad transformers work and actually is a special case of them. specialized for two particular monads. List. if passed an initial value. Monad-polymorphic operations are almost always used with monads of the first class. This is done by calling execState with a second argument of 0 (start counting from zero). composite monads that combine properties of some simpler ones. This problem is addressed by monad transformers but this topic is beyond the scope of this text. namely combining several monads in one. we saw how some non-trivial practical problems are formulated and solved in terms of monads and we also saw the usefulness of the monad abstraction and which operations may exploit this abstraction.Generates a string of the form </tag> showLeave (Node tag _) = "</"++tag++">" printTree = walk p where p (Enter node) = do printIndent (showEnter node) indentMore p (Leave node) = do indentLess printIndent (showLeave node) This trick. You can get more familiar with monad transformers in [B. Conclusion We've looked at several 'facets' of monads: we inferred the conception itself as a generalization of some imperative idioms. As we progressed. The walk function and State monad can also be used to count the number of nodes satisfying a predicate: countNodes p tree = execState (walk (\e -> when (counts e) (modify (1+))) tree) 0 where counts (Enter n) = p n counts _ = False In this code the handler is represented by a function that increases the state variable by 1 if it enters a node satisfying the predicate. The result of traversal is a value of type State Int (). This topis is especially interesting because monads were initially discovered in category theory and only later Philip Wadler applied them to programming.11].i.-.7] and [B. and it's inconvenient to write a new monad for each such case. we saw that monads are most commonly used for two different purposes: structuring the control flow and describing imperative effectful computations (IO. but we didn't study them thoroughly. Some monads belong to both classes (Parser). and structuring data flow (Maybe. Also. . t. it is not yet the answer but just a function ready to compute it. State. Dist). is needed rather often. We've also touched the topic of monad transformers. However. IndentIO).

org/tutorial/ . mostly ones similar to State 3.haskell.pdf .org/haskellwiki/Monad_tutorials_timeline .Yet Another Haskell Tutorial.psu. completely changed my understanding of how it works and helped develop a more correct version of the section about it. http://www.html .org/beta/monads.org/haskellwiki/Tutorials#Using_monads . namely.pdf . Ivan Veselov and Oleg Tsarev for valuable comments and offers to early drafts of this text and to Julia Astakhova for those to later versions.realworldhaskell.A timeline of monad tutorials with good annotations 6.org/beta/monadcase. http://www.haskell.edu/wadler95monads. bd_ and Saizan.haskell. http://book.org/haskellwiki/Monad . http://www.haskell. People from the #haskell IRC-channel also gave valuable comments on monad-polymorphic functions. .ist.org/all_about_monads/html/index.A list of monad tutorials 5.A list of Haskell tutorials B. http://www.Philip Wadler's classical article on monads that fired up interest to them 2.org/yaht/yaht. http://citeseer.A gentle introduction to Haskell 3.haskell. and that you got interested in studying topics omitted in this article. http://darcs. ddarius and roconnor pointed me to the fact that my section about the IO monad was incorrect. Ivan Tarasov.html . one of the easiest yet largest tutorials 2.haskell.haskell. http://www.html . http://book. References A.org/yaht/yaht. http://darcs.I hope that the text has succeeded in its intent to form an intuitive understanding of how monads work and a 'feeling' for them. Other monad tutorials 1. http://www.An article on haskellwiki 4.realworldhaskell.haskell. Basics of Haskell 1. Maxim Taldykin and Artem Shalkhakov helped find some errors in the published version. quicksilver.Contains a chapter on monads.html . dons. ski. Acknowledgements I would like to thank Denis Moskvin.A big and thorough tutorial describing all the standard monads and monad transformers 7.org/haskellwiki/Tutorials . for countenance and patience.

http://okmij. Erik Meijer .com/Expert-F-Experts-Voice-Net/dp/1590598504 . brilliantly tells about the IO monad 10.nl/hjgtuyl/tourdemonad.Simon Peython Jones' article 'Tackling The Awkward Squad'.org/wiki/MonadTransformers .A thorough overview of everything monad-related in Haskell's standard library 11. http://www.http://book.org/ftp/Computation/monads.haskell.com/books?hl=en&lr=&id=AiMwYZsTGkC&oi=fnd&pg=PA113&ots=prga1Pri15&sig=3Z5qGXfwK1AWI6RKZ5Jc2ubyeTg . http://www. State and IO.an article with several interesting variations on the topic of probability monads 5. http://research.ac. also a brilliant introduction to functional programming in general MonadsEn (last edited 2011-05-20 20:40:17 by max ulidtko) .Philip Wadler.ps .uk/~gmh//monparsing. Scientific articles on monads 1. http://www. Very detailed and with practical examples.cs.org/haskellwiki/Monads_as_containers 9.folding-maps.org/blog/archives/2008/03/29/io-monad-the-continuation-presentation/ A blog post by Luke Palmer that explains how the IO monad might be implemented with continuations D.html .realworldhaskell.html .Mikhail Mitrofanov's presentation about monad transformers (in Russian) C.microsoft.net/darcs/probability-monads/probability-monads.Monadic Parser Combinators 4.Chapters of the 'Real World Haskell' book about monads. 'Build your own probability monads' .org/beta/monadtrans. 8.The book 'Expert F#'.nott. 'How to replace failure by a list of successes' 2.chello.Graham Hutton. Other 1. http://www. including the monad of statistical experiments (Monte-Carlo method) and the monad of logical inference 3.randomhacks.amazon.pdf . http://members.com/~simonpj/papers/marktoberdorf/ . Mostly about Maybe. http://luqui. http://books.google.Oleg Kiselyov's articles on monads. http://spbhug.Eric Kidd.html .

Are you sure?

This action might not be possible to undo. Are you sure you want to continue?

We've moved you to where you read on your other device.

Get the full title to continue

Get the full title to continue listening from where you left off, or restart the preview.

scribd