Category:Monads

From Rosetta Code
Revision as of 05:11, 1 February 2016 by rosettacode>Domgetter (moved list monad examples over)
Monads is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

In functional programming, the Monad pattern is a general solution to the problem of nesting (or 'composing') functions when the data to which they apply is enclosed in some kind of useful wrapping. It involves implementing two higher-order functions which, between them, can take care of ensuring that the nested (data-transforming) functions are not choked by being called on unexpected types of data. (Wrapped data, when they were expecting something raw and unwrapped).

The two higher-order functions which make up the monad pattern handle the details of: 1. wrapping and unwrapping data, and 2. Providing other functions with direct access to the unwrapped data contents. Delegating the mechanics to these two meta-functions allows the programmer to work with a simple and well-understood generic model, and to nest functions transparently.

The two monad functions are sometimes named as follows:

  1. 'Return' or 'unit' which wraps a piece of raw data, returning the wrapped 'monadic' form.
  2. 'Bind' which applies some other function directly to the contents of a monadic wrapper, obtains a result, and returns a wrapped form of that result.


(The term monad derives from a concept in category theory. In ancient Greek the word μοναδικος means 'consisting of units').

Commonly used monads include the Maybe monad, (in which the wrapper encodes whether or not the raw content is a legal value for a particular type of function), and the List monad, in which raw data is simply contained in a list. When lists are used to represent a range of possible values for a variable name, nesting functions which act on these lists allows a convenient encoding of cartesian products and set comprehensions. In this context, the two higher order monad functions ensure that each data-transforming function (in a nest or composition of such functions) gets the right kind of argument (Raw atomic values versus one or more values 'wrapped in' a list).

(Other frequently used monads are the IO monad and the State monad)

Demonstrate in your programming language the following:

  1. Construct a Monad (preferably the Option/Maybe Monad or the List Monad) by writing the 'bind' function and the 'unit' (sometimes known as 'return') function for that Monad (or just use what the language already has implemented)
  2. Make two functions, each which take a number and return a monadic number, e.g. Int -> Maybe Int and Int -> Maybe String
  3. Compose the two functions with bind

Clojure

Maybe Monad

<lang clojure> (defn bind [val f] (if (nil? (:value val)) val (f (:value val)))) (defn unit [val] {:value val})

(defn opt_add_3 [n] (unit (+ 3 n))) ; takes a number and returns a Maybe number (defn opt_str [n] (unit (str n)))  ; takes a number and returns a Maybe string

(bind (unit 4) opt_add_3)  ; evaluates to {:value 7} (bind (unit nil) opt_add_3)  ; evaluates to {:value nil} (bind (bind (unit 8) opt_add_3) opt_str)  ; evaluates to {:value "11"} (bind (bind (unit nil) opt_add_3) opt_str) ; evaluates to {:value nil} </lang>


zkl

While I'm unsure of the utility of Monads in a dynamic type-less language, it can be done.

Maybe Monad

From the Wikipedia

Here we use the Void object as Nothing and define some functions. Sine zkl is type-less, we can consider Maybe as a native type and don't need to define it. <lang zkl>fcn bind(a,type,b){ if(type.isType(a)) b else Void } fcn just(x){ if(Deferred.isType(x)) x() else x } // force lazy evaluation fcn rtn(x) { just(x) }</lang> Since zkl is eager, add needs to gyrate a bit by creating a lazy result and evaluating that after the binds have done their bizness. <lang zkl>fcn add(mx,my){

  bind(mx,Int,
     bind(my,Int,
       '+.fp(mx,my))) : rtn(_)  // create a lazy mx+my to avoid eager eval

} add(1,2).println(); // two ints add(1,2.0).println(); // int and float add(self,2).println(); // class and int</lang>

Output:
3
Void
Void

Pages in category "Monads"

The following 3 pages are in this category, out of 3 total.