rlm@10: ;; Test routines for monads.clj rlm@10: rlm@10: ;; by Konrad Hinsen rlm@10: ;; last updated March 28, 2009 rlm@10: rlm@10: ;; Copyright (c) Konrad Hinsen, 2008. All rights reserved. The use rlm@10: ;; and distribution terms for this software are covered by the Eclipse rlm@10: ;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) rlm@10: ;; which can be found in the file epl-v10.html at the root of this rlm@10: ;; distribution. By using this software in any fashion, you are rlm@10: ;; agreeing to be bound by the terms of this license. You must not rlm@10: ;; remove this notice, or any other, from this software. rlm@10: rlm@10: (ns clojure.contrib.test-monads rlm@10: (:use [clojure.test :only (deftest is are run-tests)] rlm@10: [clojure.contrib.monads rlm@10: :only (with-monad domonad m-lift m-seq m-chain rlm@10: sequence-m maybe-m state-m maybe-t sequence-t)])) rlm@10: rlm@10: (deftest sequence-monad rlm@10: (with-monad sequence-m rlm@10: (are [a b] (= a b) rlm@10: (domonad [x (range 3) y (range 2)] (+ x y)) rlm@10: '(0 1 1 2 2 3) rlm@10: (domonad [x (range 5) y (range (+ 1 x)) :when (= (+ x y) 2)] (list x y)) rlm@10: '((1 1) (2 0)) rlm@10: ((m-lift 2 #(list %1 %2)) (range 3) (range 2)) rlm@10: '((0 0) (0 1) (1 0) (1 1) (2 0) (2 1)) rlm@10: (m-seq (replicate 3 (range 2))) rlm@10: '((0 0 0) (0 0 1) (0 1 0) (0 1 1) (1 0 0) (1 0 1) (1 1 0) (1 1 1)) rlm@10: ((m-chain (replicate 3 range)) 5) rlm@10: '(0 0 0 1 0 0 1 0 1 2) rlm@10: (m-plus (range 3) (range 2)) rlm@10: '(0 1 2 0 1)))) rlm@10: rlm@10: (deftest maybe-monad rlm@10: (with-monad maybe-m rlm@10: (let [m+ (m-lift 2 +) rlm@10: mdiv (fn [x y] (domonad [a x b y :when (not (zero? b))] (/ a b)))] rlm@10: (are [a b] (= a b) rlm@10: (m+ (m-result 1) (m-result 3)) rlm@10: (m-result 4) rlm@10: (mdiv (m-result 1) (m-result 3)) rlm@10: (m-result (/ 1 3)) rlm@10: (m+ 1 (mdiv (m-result 1) (m-result 0))) rlm@10: m-zero rlm@10: (m-plus m-zero (m-result 1) m-zero (m-result 2)) rlm@10: (m-result 1))))) rlm@10: rlm@10: (deftest seq-maybe-monad rlm@10: (with-monad (maybe-t sequence-m) rlm@10: (letfn [(pairs [xs] ((m-lift 2 #(list %1 %2)) xs xs))] rlm@10: (are [a b] (= a b) rlm@10: ((m-lift 1 inc) (for [n (range 10)] (when (odd? n) n))) rlm@10: '(nil 2 nil 4 nil 6 nil 8 nil 10) rlm@10: (pairs (for [n (range 5)] (when (odd? n) n))) rlm@10: '(nil nil (1 1) nil (1 3) nil nil nil (3 1) nil (3 3) nil nil))))) rlm@10: rlm@10: (deftest state-maybe-monad rlm@10: (with-monad (maybe-t state-m) rlm@10: (is (= (for [[a b c d] (list [1 2 3 4] [nil 2 3 4] [ 1 nil 3 4] rlm@10: [nil nil 3 4] [1 2 nil nil])] rlm@10: (let [f (domonad rlm@10: [x (m-plus (m-result a) (m-result b)) rlm@10: y (m-plus (m-result c) (m-result d))] rlm@10: (+ x y))] rlm@10: (f :state))) rlm@10: (list [4 :state] [5 :state] [4 :state] [nil :state] [nil :state]))))) rlm@10: rlm@10: (deftest state-seq-monad rlm@10: (with-monad (sequence-t state-m) rlm@10: (is (= (let [[a b c d] [1 2 10 20] rlm@10: f (domonad rlm@10: [x (m-plus (m-result a) (m-result b)) rlm@10: y (m-plus (m-result c) (m-result d))] rlm@10: (+ x y))] rlm@10: (f :state))) rlm@10: (list [(list 11 21 12 22) :state]))))