# 'Return' or 'unit' which wraps a piece of raw data, returning the wrapped 'monadic' form.
# '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 [[wp:Monad_(category_theory)|a concept in category theory]]. In ancient Greek the word μοναδικος means 'consisting of units').
(Other frequently used monads are the IO monad and the State monad)
Demonstrate in your programming language the following:
# 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)
# Make two functions, each which take a number and return a monadic number, e.g. <code>Int -> Maybe Int</code> and <code>Int -> Maybe String</code>
# Compose the two functions with bind
=={{header|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>
=={{header|zkl}}==
While I'm unsure of the utility of Monads in a dynamic type-less language, it can be done.
===Maybe Monad===
From the [[wp:Monad_(functional_programming)#The_Maybe_monad|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>
{{out}}
<pre>
3
Void
Void
</pre>
|