I have found these resources the most helpful:

- Adam Smyczek's Introduction to Monads on YouTube
- Santosh Rajan's blog Functional JavaScript
- Jim Duey's discussion of monads on his blog about Clojure

In all of the discussions I have seen, it is stressed that monads are defined in terms of the behaviour of two functions.

- result, m_result, mResult, etc.
- return, m_return, etc.
- lift, m_lift, etc.
- the monadic function (? Sometimes. However, the 2nd argument to rewrap —see below— is generally called
*monadic function*, so it may be more accurate to describe wrap as the base function on which all other monadic functions of a given monad are built.)

When he discusses the Array Monad for Javascript, Santosh Rajan gives the following signature for *the monadic function*, i.e. wrap.

f: T -> [T]That is, for the Array Monad, wrap takes a value of some type T, and

The resulting, wrapped, value returned from wrap is known as a

You can see why;; Takes a basic value; returns a wrapt value (defn mymonad-wrap [bv] (let [wrapt (do-the-wrapping-ofbv)] wrapt))

unwrap is the inverse of wrap, not surprisingly. In terms of Santosh's Array monad, it's signature might look like this.

f: T <- [T]That is, unwrap takes a

M: [T] -> [T]That is, it transforms a

rewrap looks like this.

So, what rewrap does is(defn mymonad-rewrap [wrapt, mf] ;; call monadic function given as 2nd arg, on the ;; basic value extracted from the wrapt value given ;; in the 1st argument. Return the new wrapt value. (let [bv (do-unwrap-fn-on wrapt) new-wrapt (mf bv)] new-wrapt))

- unwrap its
*monadic value*argument to get the*basic value* - call its
*monadic function*argument with the unwrapped*basic value*to...- modify the
*basic value* - wrap the modified
*basic value*and return a new*wrapt value*

- modify the

mf ⇒ (f′ ⋅ wrap)where f′ is a function that modifies the

wrap′ ⇒ (identity ⋅ wrap)That given, we can now describe rewrap as

or, equivalently,`(defn rewrap [wrapt, (f′ ⋅ wrap)]`

(let [bv (unwrap wrapt) new-wrapt (wrap (f′ bv))] new-wrapt))

`(defn rewrap [wrapt, (f′ ⋅ wrap)]`

`(wrap (f′ (unwrap wrapt))))`

(rewrap (wrap x) f) ≡ (f x)Alternatively, given our rewriting of rewrap, above, but using f rather than (f′ ⋅ wrap);

(f (unwrap (wrap x)) ≡ (f x)

⇒ (f x) ≡ (f x)

(rewrap wrapt wrap) ≡ wrapt

⇒ (wrap (unwrap wrapt)) ≡ wrapt

⇒ wrapt ≡ wrapt

(rewrap (rewrap wrapt f) g) ≡Everything looks pretty straightforward, except for the correspondence between [1] and [2] in Rule 3. Something seems odd about it, even though the results will be the same.

(rewrap wrapt (fn [x] (rewrap (f x) g)))

LHS ⇒ (rewrap (f (unwrap wrapt)) g)

⇒ (g (unwrap (f (unwrap wrapt))))

⇒ (g (unwrap (f x))) [1]

⇒ (g (unwrap (wrap (f′ x))))

⇒ (g (f′ x))

RHS ⇒ (rewrap wrapt (fn [x] (g (unwrap (f x)))))

⇒ ((fn [x] (g (unwrap (f x)))) (unwrap wrapt))

⇒ ((fn [x] (g (unwrap (f x)))) x) [2]