aboutsummaryrefslogtreecommitdiff
path: root/src/clojure/contrib/monads
diff options
context:
space:
mode:
authorKonrad Hinsen <konrad.hinsen@laposte.net>2009-01-12 15:48:13 +0000
committerKonrad Hinsen <konrad.hinsen@laposte.net>2009-01-12 15:48:13 +0000
commit035066ceb18b7b73991e5f00037a0dd7a2d4c8cb (patch)
treecf79adf2f83030c986088c112c0a57d9fb15711f /src/clojure/contrib/monads
parent2b1e44f04489b5d70faff703bf824f07b74432d2 (diff)
Monads: Added examples and test cases for (maybe-t sequence)
Diffstat (limited to 'src/clojure/contrib/monads')
-rw-r--r--src/clojure/contrib/monads/examples.clj46
-rw-r--r--src/clojure/contrib/monads/test.clj15
2 files changed, 59 insertions, 2 deletions
diff --git a/src/clojure/contrib/monads/examples.clj b/src/clojure/contrib/monads/examples.clj
index 8ddf91be..2cb2d5ce 100644
--- a/src/clojure/contrib/monads/examples.clj
+++ b/src/clojure/contrib/monads/examples.clj
@@ -241,4 +241,50 @@
(list [x1 x2] [y1 y2])))
(identical-random-seqs 1)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Sequences with undefined value: the maybe-t monad transformer
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; A monad transformer is a function that takes a monad argument and
+; returns a monad as its result. The resulting monad adds some
+; specific behaviour aspect to the input monad.
+
+; The simplest monad transformer is maybe-t. It adds the functionality
+; of the maybe monad (handling failures or undefined values) to any other
+; monad. We illustrate this by applying maybe-t to the sequence monad.
+; The result is an enhanced sequence monad in which undefined values
+; (represented by nil) are not subjected to any transformation, but
+; lead immediately to a nil result in the output.
+
+; First we define the combined monad:
+(def seq-maybe (maybe-t sequence))
+
+; As a first illustration, we create a range of integers and replace
+; all even values by nil, using a simple when expression. We use this
+; sequence in a monad comprehension that yields (inc x). The result
+; is a sequence in which inc has been applied to all non-nil values,
+; whereas the nil values appear unmodified in the output:
+(domonad seq-maybe
+ [x (for [n (range 10)] (when (odd? n) n))]
+ (inc x))
+
+; Next we repeat the definition of the function pairs (see above), but
+; using the seq-maybe monad:
+(with-monad seq-maybe
+ (defn pairs-maybe [xs]
+ (m-seq (list xs xs))))
+
+; Applying this to a sequence containing nils yields the pairs of all
+; non-nil values interspersed with nils that result from any combination
+; in which one or both of the values is nil:
+(pairs-maybe (for [n (range 5)] (when (odd? n) n)))
+
+; It is important to realize that undefined values (nil) are not eliminated
+; from the iterations. They are simply not passed on to any operations.
+; The outcome of any function applied to arguments of which at least one
+; is nil is supposed to be nil as well, and the function is never called.
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/src/clojure/contrib/monads/test.clj b/src/clojure/contrib/monads/test.clj
index b63b8946..661fd2a4 100644
--- a/src/clojure/contrib/monads/test.clj
+++ b/src/clojure/contrib/monads/test.clj
@@ -1,7 +1,7 @@
;; Test routines for monads.clj
;; by Konrad Hinsen
-;; last updated December 31, 2008
+;; last updated January 12, 2009
;; Copyright (c) Konrad Hinsen, 2008. All rights reserved. The use
;; and distribution terms for this software are covered by the Eclipse
@@ -12,7 +12,9 @@
;; remove this notice, or any other, from this software.
(ns clojure.contrib.test-monads
- (:use clojure.contrib.test-is clojure.contrib.monads))
+ (:use clojure.contrib.test-is
+ clojure.contrib.monads
+ clojure.contrib.macros))
(deftest sequence-monad
(with-monad sequence
@@ -44,4 +46,13 @@
(m-plus m-zero (m-result 1) m-zero (m-result 2))
(m-result 1)))))
+(deftest seq-maybe-monad
+ (with-monad (maybe-t sequence)
+ (letfn [pairs [xs] ((m-lift 2 #(list %1 %2)) xs xs)]
+ (are (= _1 _2)
+ ((m-lift 1 inc) (for [n (range 10)] (when (odd? n) n)))
+ '(nil 2 nil 4 nil 6 nil 8 nil 10)
+ (pairs (for [n (range 5)] (when (odd? n) n)))
+ '(nil nil (1 1) nil (1 3) nil nil nil (3 1) nil (3 3) nil nil)))))
+
(run-tests)