    monadic context, map it into the given collection
    calling m-sequence on the results.
 
-       (require '[cats.types :as t])
-       (require '[cats.core :as m])
-
-       (m/m-map t/just [2 3])
-       ;=> <Just [[2 3]]>
-
-       (m/m-map (fn [v]
-                  (if (odd? v)
-                    (t/just v)
-                    (t/nothing)))
-                 [1 2])
-       ;=> <Nothing>
-     "
+     (require '[cats.types :as t])
+     (require '[cats.core :as m])
+
+     (m/m-map t/just [2 3])
+     ;=> <Just [[2 3]]>
+
+     (m/m-map (fn [v]
+                (if (odd? v)
+                  (t/just v)
+                  (t/nothing)))
+               [1 2])
+     ;=> <Nothing>
+  "
   [mf coll]
   (m-sequence (map mf coll)))
 
 (defn m-for
   "Same as m-map but with the arguments in reverse order.
 
-      (require '[cats.types :as t])
-      (require '[cats.core :as m])
-
-      (m/m-for [2 3] t/just)
-      ;=> <Just [[2 3]]>
-
-      (m/m-for [1 2]
-               (fn [v]
-                  (if (odd? v)
-                    (t/just v)
-                    (t/nothing))))
-      ;=> <Nothing>
-   "
+    (require '[cats.types :as t])
+    (require '[cats.core :as m])
+
+    (m/m-for [2 3] t/just)
+    ;=> <Just [[2 3]]>
+
+    (m/m-for [1 2]
+             (fn [v]
+                (if (odd? v)
+                  (t/just v)
+                  (t/nothing))))
+    ;=> <Nothing>
+  "
   [vs mf]
   (m-map mf vs))
-
-(defmacro m-lift
-  "Lifts a function with the given fixed number of arguments to a
-  monadic context.
-
-      (require '[cats.types :as t])
-      (require '[cats.core :as m])
-
-      (def monad+ (m/m-lift 2 +))
-
-      (monad+ (t/just 1) (t/just 2))
-      ;=> <Just [3]>
-
-      (monad+ (t/just 1) (t/nothing))
-      ;=> <Nothing>
-
-      (monad+ [0 2 4] [1 2])
-      ;=> [1 2 3 4 5 6]
-  "
-  [n f]
-  (let [val-syms (repeatedly n gensym)
-        mval-syms (repeatedly n gensym)
-        mlet-bindings (interleave val-syms mval-syms)]
-    `(fn [~@mval-syms]
-       (mlet [~@mlet-bindings]
-         (return (~f ~@val-syms))))))
 
 (defn m-filter
   "Applies a predicate to a value in a `MonadZero` instance,

  #+cljs
  (:require-macros [cats.core :as cm]))


(def ^:dynamic *m-context*)


                  :when (p v)]
                  (return v)))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Haskell-style aliases and util functions.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defn <$>
  "Alias of fmap."
  ([f]
     (fn [fv]
       (p/fmap fv f)))
  ([f fv]
     (p/fmap fv f)))

(defn <*>
  "Performs a Haskell-style left-associative fapply."
  ([af av]
     (p/fapply af av))
  ([af av & avs]
     (reduce p/fapply af (cons av avs))))

(defn >>=
  "Performs a Haskell-style left-associative bind.

  Example:
    (>>= (just 1) (comp just inc) (comp just inc))
    ;=> #<Just [3]>
  "
  ([mv f]
     (bind mv f))
  ([mv f & fs]
     (reduce bind mv (cons f fs))))

(defn =<<
  "Same as the two argument version of `>>=` but with the
  arguments interchanged."
  [f mv]
  (>>= mv f))

(defn >=>
  "Left-to-right composition of monads."
  [mf mg x]
  (#+clj  mlet
   #+cljs cm/mlet [a (mf x)
                   b (mg a)]
                  (return b)))

(defn <=<
  "Right-to-left composition of monads.
  Same as `>=>` with its first two arguments flipped."
  [mg mf x]
  (#+clj  mlet
   #+cljs cm/mlet [a (mf x)
                   b (mg a)]
                  (return b)))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; State monad functions
