Skip to content

Instantly share code, notes, and snippets.

@michaelsbradleyjr
Created October 31, 2012 19:39
Show Gist options
  • Save michaelsbradleyjr/3989325 to your computer and use it in GitHub Desktop.
Save michaelsbradleyjr/3989325 to your computer and use it in GitHub Desktop.
hacking maybe-monad in protocol-monads
#_(defn plus [[mv & mvs]]
(plus-step mv mvs))
(defmacro plus [mvs]
`(let [mvs# (quote ~mvs)
mv# (eval (first mvs#))]
(monads.core/plus-step mv# (rest mvs#))))
(deftype maybe-monad [v]
clojure.lang.IDeref
(deref [_]
v)
Monad
(do-result [_ v]
(maybe-monad. v))
(bind [mv f]
(if (= mv maybe-zero-val)
maybe-zero-val
(f @mv)))
MonadZero
(zero [_]
maybe-zero-val)
(plus-step [mv mvs]
(let [mv (loop [mv mv
rvs mvs]
(let [mv (if (= (class mv) maybe-monad)
mv
(eval mv))]
(if (not= maybe-zero-val mv)
mv
(if (empty? rvs)
nil
(recur (first rvs)
(rest rvs))))))]
(if (nil? mv)
maybe-zero-val
mv))))
;; the test will now pass, i.e. it won't throw an exception
(deftest maybe-plus
(is (= :bogus
@(m/plus [(m/maybe :bogus)
(m/do m/maybe
[_ (m/maybe 1)]
(throw (Exception. "Should not be thrown")))]))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment