diff options
author | Konrad Hinsen <konrad.hinsen@laposte.net> | 2009-01-12 15:48:13 +0000 |
---|---|---|
committer | Konrad Hinsen <konrad.hinsen@laposte.net> | 2009-01-12 15:48:13 +0000 |
commit | 035066ceb18b7b73991e5f00037a0dd7a2d4c8cb (patch) | |
tree | cf79adf2f83030c986088c112c0a57d9fb15711f /src/clojure/contrib/monads | |
parent | 2b1e44f04489b5d70faff703bf824f07b74432d2 (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.clj | 46 | ||||
-rw-r--r-- | src/clojure/contrib/monads/test.clj | 15 |
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) |