diff --git a/src/main/clojure/clojure/algo/monads.clj b/src/main/clojure/clojure/algo/monads.clj index 5efbaff..177c393 100644 --- a/src/main/clojure/clojure/algo/monads.clj +++ b/src/main/clojure/clojure/algo/monads.clj @@ -267,6 +267,17 @@ (m-result '()) (reverse ms))) +(defmonadfn m-lift-fn + "A purely functional replacement for m-lift + ((m-lift 2 +) (m-result 5) (m-result 6)) should be equal to + ((m-lift-fn +) (m-result 5) (m-result-6)) + Note that this is untested" + [f] + (fn [& args] + (m-bind + (m-seq args) + #(m-result (apply f %))))) + (defmonadfn m-map "'Executes' the sequence of monadic values resulting from mapping f onto the values xs. f must return a monadic value." diff --git a/src/test/clojure/clojure/algo/test_monads.clj b/src/test/clojure/clojure/algo/test_monads.clj index bd6282f..9baa93e 100644 --- a/src/test/clojure/clojure/algo/test_monads.clj +++ b/src/test/clojure/clojure/algo/test_monads.clj @@ -12,7 +12,7 @@ (:use [clojure.test :only (deftest is are run-tests)] [clojure.algo.monads :only (with-monad domonad m-lift m-seq m-chain writer-m write - sequence-m maybe-m state-m maybe-t sequence-t)])) + sequence-m maybe-m state-m maybe-t sequence-t m-lift-fn)])) (deftest domonad-if-then @@ -95,6 +95,22 @@ '(0 0 0 1 0 0 1 0 1 2) (m-plus (range 3) (range 2)) '(0 1 2 0 1)))) + +(deftest sequence-monad-using-m-lift-fn + (with-monad sequence-m + (are [a b] (= a b) + (domonad [x (range 3) y (range 2)] (+ x y)) + '(0 1 1 2 2 3) + (domonad [x (range 5) y (range (+ 1 x)) :when (= (+ x y) 2)] (list x y)) + '((1 1) (2 0)) + ((m-lift-fn #(list %1 %2)) (range 3) (range 2)) + '((0 0) (0 1) (1 0) (1 1) (2 0) (2 1)) + (m-seq (replicate 3 (range 2))) + '((0 0 0) (0 0 1) (0 1 0) (0 1 1) (1 0 0) (1 0 1) (1 1 0) (1 1 1)) + ((m-chain (replicate 3 range)) 5) + '(0 0 0 1 0 0 1 0 1 2) + (m-plus (range 3) (range 2)) + '(0 1 2 0 1)))) (deftest maybe-monad (with-monad maybe-m