 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (defn run-cont
-  [cont]
   "Given a Continuation instance, execute the
   wrapped computation and return its value."
+  [cont]
   (#+clj  with-context
    #+cljs cm/with-context cont
     (cont identity)))

  (>>= mv f))

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

(defn <=<
  [mg mf x]
  "Right-to-left composition of monads.

  Same as `>=>` with its first two arguments flipped."
  (#+clj  mlet
   #+cljs cm/mlet [a (mf x)
                   b (mg a)]
                  (return b)))

(defn sequence-m
  [mvs]
  {:pre [(not-empty mvs)]}
  (reduce (fn [mvs mv]

            (return []))
          mvs))

(defn map-m
   "Given a function that takes a value and puts it into a
   monadic context, map it into the given collection
   calling sequence-m on the results.

       (require '[cats.types :as t])
       (require '[cats.core :as m])

       (m/map-m t/just [2 3])
       ;=> <Just [[2 3]]>

       (m/for-m (fn [v]
                   (if (odd? v)
                     (t/just v)
                     (t/nothing)))
                [1 2])
       ;=> <Nothing>
     "
  [mf coll]
  (sequence-m (map mf coll)))

(defn for-m
  "Same as map-m but with the arguments in reverse order.

      (require '[cats.types :as t])
      (require '[cats.core :as m])

      (m/for-m [2 3] t/just)
      ;=> <Just [[2 3]]>

      (m/for-m [1 2]
               (fn [v]
                  (if (odd? v)
                    (t/just v)
                    (t/nothing))))
      ;=> <Nothing>
   "
  [vs mf]
  (map-m mf vs))

