aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStuart Halloway <stu@thinkrelevance.com>2009-06-24 00:48:39 -0400
committerStuart Halloway <stu@thinkrelevance.com>2009-06-24 00:48:39 -0400
commit17e6a5c17a9f0577f749632b81e3900a383405c6 (patch)
tree40ed36803c5389e2b4558acb42107e9d6031a8d8 /src
parent0930bfdf3361f76d773149b5bd7170c435fe5f20 (diff)
parent6823c51380b69ec12f641fbef09d395237931e40 (diff)
Merge commit 'rich/master' into gtic
Diffstat (limited to 'src')
-rw-r--r--src/clojure/contrib/monads.clj57
1 files changed, 49 insertions, 8 deletions
diff --git a/src/clojure/contrib/monads.clj b/src/clojure/contrib/monads.clj
index 476e649e..68e03c13 100644
--- a/src/clojure/contrib/monads.clj
+++ b/src/clojure/contrib/monads.clj
@@ -1,7 +1,7 @@
;; Monads in Clojure
;; by Konrad Hinsen
-;; last updated May 10, 2009
+;; last updated June 23, 2009
;; Copyright (c) Konrad Hinsen, 2009. All rights reserved. The use
;; and distribution terms for this software are covered by the Eclipse
@@ -238,8 +238,20 @@
m-val (m-result val)]
(reduce m-f m-val mvs))))
+(defmonadfn m-until
+ "While (p x) is false, replace x by the value returned by the
+ monadic computation (f x). Return (m-result x) for the first
+ x for which (p x) is true."
+ [p f x]
+ (if (p x)
+ (m-result x)
+ (domonad
+ [y (f x)
+ z (m-until p f y)]
+ z)))
+
(defmacro m-when
- "If test if logical true, return monadic value m-expr, else return
+ "If test is logical true, return monadic value m-expr, else return
(m-result nil)."
[test m-expr]
`(if ~test ~m-expr (~'m-result nil)))
@@ -332,42 +344,71 @@
((f v) ss))))
])
-(defn update-state [f]
+(defn update-state
"Return a state-monad function that replaces the current state by the
result of f applied to the current state and that returns the old state."
+ [f]
(fn [s] [s (f s)]))
-(defn set-state [s]
+(defn set-state
"Return a state-monad function that replaces the current state by s and
returns the previous state."
+ [s]
(update-state (fn [_] s)))
-(defn fetch-state []
+(defn fetch-state
"Return a state-monad function that returns the current state and does not
modify it."
+ []
(update-state identity))
-(defn fetch-val [key]
+(defn fetch-val
"Return a state-monad function that assumes the state to be a map and
returns the value corresponding to the given key. The state is not modified."
+ [key]
(domonad state-m
[s (fetch-state)]
(key s)))
-(defn update-val [key f]
+(defn update-val
"Return a state-monad function that assumes the state to be a map and
replaces the value associated with the given key by the return value
of f applied to the old value. The old value is returned."
+ [key f]
(fn [s]
(let [old-val (get s key)
new-s (assoc s key (f old-val))]
[old-val new-s])))
-(defn set-val [key val]
+(defn set-val
"Return a state-monad function that assumes the state to be a map and
replaces the value associated with key by val. The old value is returned."
+ [key val]
(update-val key (fn [_] val)))
+(defn with-state-field
+ "Returns a state-monad function that expects a map as its state and
+ runs statement (another state-monad function) on the state defined by
+ the map entry corresponding to key. The map entry is updated with the
+ new state returned by statement."
+ [key statement]
+ (fn [s]
+ (let [substate (get s key nil)
+ [result new-substate] (statement substate)
+ new-state (assoc s key new-substate)]
+ [result new-state])))
+
+(defn state-m-until
+ "An optimized implementation of m-until for the state monad that
+ replaces recursion by a loop."
+ [p f x]
+ (letfn [(until [p f x s]
+ (if (p x)
+ [x s]
+ (let [[x s] ((f x) s)]
+ (recur p f x s))))]
+ (fn [s] (until p f x s))))
+
; Writer monad
(defn writer-m
"Monad describing computations that accumulate data on the side, e.g. for