Skip to content

Commit

Permalink
Attempt at the reader monad and transformer
Browse files Browse the repository at this point in the history
  • Loading branch information
Jim Duey committed Oct 24, 2013
1 parent 4a00113 commit 1847cdd
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 5 deletions.
82 changes: 77 additions & 5 deletions src/clj/monads/core.clj
Expand Up @@ -93,6 +93,12 @@
(writer-m-combine [container1 container2]
"combine two containers, return new container"))

(extend-type clojure.lang.PersistentArrayMap
MonadWriter
(writer-m-empty [_] (hash-map))
(writer-m-add [c v] (conj c v))
(writer-m-combine [c1 c2] (merge c1 c2)))

(extend-type clojure.lang.PersistentList
Monad
(do-result [_ v]
Expand Down Expand Up @@ -379,6 +385,35 @@
(writer-m-add [c v] (str c v))
(writer-m-combine [c1 c2] (str c1 c2)))

(deftype reader-monad [v mv f]
clojure.lang.IFn
(invoke [_ e]
(if f
(let [v (mv e)]
((f v) e))
v))

Monad
(do-result [_ v]
(reader-monad. v nil nil))
(bind [mv f]
(reader-monad. nil mv f)))

(def get-env
(reify
clojure.lang.IFn
(invoke [_ e]
e)

Monad
(do-result [_ v]
(reader-monad. v nil nil))
(bind [mv f]
(reader-monad. nil mv f))))

(defn reader [v]
(reader-monad. v nil nil))

(deftype writer-monad [v accumulator]
clojure.lang.IDeref
(deref [_]
Expand Down Expand Up @@ -418,15 +453,16 @@
clojure.lang.IFn
(invoke [_ s]
(cond
alts (if (satisfies? MonadZero m)
alts (if (satisfies? MonadZero (first alts))
(plus (clojure.core/map #(% s) alts)))
f (bind (mv s)
(fn [[v ss]]
((f v) ss)))
:else (if (and (satisfies? MonadZero m)
(= v (zero (m nil))))
v
(m [v s]))))
:else (let [mv-nil (m nil)]
(if (and (satisfies? MonadZero mv-nil)
(= v (zero mv-nil)))
v
(m [v s])))))

Monad
(do-result [_ v]
Expand Down Expand Up @@ -623,3 +659,39 @@
(let [writer-m (writer accumulator)]
(fn [v]
(writer-transformer. m (m (writer-m v)) writer-m))))


(deftype reader-transformer [m v mv f alts]
clojure.lang.IFn
(invoke [_ s]
(cond
alts (if (satisfies? MonadZero (first alts))
(plus (clojure.core/map #(% s) alts)))
f (bind (mv s)
(fn [v]
((f v) s)))
:else (let [mv-nil (m nil)]
(if (and (satisfies? MonadZero mv-nil)
(= v (zero mv-nil)))
v
(m v)))))

Monad
(do-result [_ v]
(reader-transformer. m v nil nil nil))
(bind [mv f]
(reader-transformer. m nil mv f nil))

MonadZero
(zero [_]
(reader-transformer. m nil
(fn [s] (zero (m nil)))
(fn [v]
(reader-transformer. m v nil nil nil))
nil))
(plus-step [mv mvs]
(reader-transformer. m nil nil nil (cons mv mvs))))

(defn reader-t [m]
(fn [v]
(reader-transformer. m v nil nil nil)))
25 changes: 25 additions & 0 deletions test/clj/monads/test/core_test.clj
Expand Up @@ -121,6 +121,31 @@

;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defn reader-f [n]
(m/reader (inc n)))

(defn reader-g [n]
(m/reader (+ n 5)))

(deftest first-law-reader
(it ""
(is (= ((m/bind (m/reader 10) reader-f) :env)
((reader-f 10) :env)))))

(deftest second-law-reader
(it ""
(is (= ((m/bind (m/reader 10) m/reader) :env)
((m/reader 10) :env)))))

(deftest third-law-reader
(it ""
(is (= ((m/bind (m/bind (m/reader 3) reader-f) reader-g) :env)
((m/bind (m/reader 3)
(fn [x]
(m/bind (reader-f x) reader-g))) :env)))))

;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(def test-writer (m/writer #{}))

(defn writer-f [n]
Expand Down

0 comments on commit 1847cdd

Please sign in to comment.