Monad (functional Programming) - Do-notation

Although there are times when it makes sense to use the bind operator >>= directly in a program, it is more typical to use a format called do-notation (perform-notation in OCaml, computation expressions in F#), that mimics the appearance of imperative languages. The compiler translates do-notation to expressions involving >>=. For example, the following code:

a = do x <- return (x, 42)

is transformed during compilation into:

a = >>= (\x -> >>= (\_ -> return (x, 42)))

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 = fail s =

Therefore, the following transformations hold and all the following expressions are equivalent:

a = >>= (\x -> >>= (\_ -> return (x, 42))) a = >>= (\x -> concatMap (\_ -> return (x, 42)) ) a = >>= (\x -> ) a = concatMap (\x -> ) a =

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, 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 >>= (\b -> if b == 0 then Nothing else Just (a / b)))

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(readNum, fun x -> maybe.Bind(readNum, fun y -> if (y=0) then None else maybe.Return( x/y ))))

Read more about this topic:  Monad (functional Programming)