diff options
author | Konrad Hinsen <konrad.hinsen@laposte.net> | 2009-02-18 08:21:55 +0000 |
---|---|---|
committer | Konrad Hinsen <konrad.hinsen@laposte.net> | 2009-02-18 08:21:55 +0000 |
commit | 0b8c49ab33e7163e4fee94452f03dc3f47df99c2 (patch) | |
tree | 8cf24cb21fe92209f119cef6bec02f1f9637794b | |
parent | e3c982f1a9c5cde3e7e8a894889ed6367242892f (diff) |
monads+probabilities: added an -m suffix to all monad names
-rw-r--r-- | src/clojure/contrib/monads.clj | 15 | ||||
-rw-r--r-- | src/clojure/contrib/monads/examples.clj | 50 | ||||
-rw-r--r-- | src/clojure/contrib/monads/test.clj | 8 | ||||
-rw-r--r-- | src/clojure/contrib/probabilities/dist.clj | 17 | ||||
-rw-r--r-- | src/clojure/contrib/probabilities/dist/examples.clj | 18 |
5 files changed, 53 insertions, 55 deletions
diff --git a/src/clojure/contrib/monads.clj b/src/clojure/contrib/monads.clj index a9331c02..838a4221 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 February 15, 2009 +;; last updated February 18, 2009 ;; Copyright (c) Konrad Hinsen, 2009. All rights reserved. The use ;; and distribution terms for this software are covered by the Eclipse @@ -12,7 +12,6 @@ ;; remove this notice, or any other, from this software. (ns clojure.contrib.monads - (:refer-clojure :exclude (sequence)) (:require [clojure.contrib.accumulators])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -210,7 +209,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Identity monad -(defmonad id +(defmonad identity-m "Monad describing plain computations. This monad does in fact nothing at all. It is useful for testing, for combination with monad transformers, and for code that is parameterized with a monad." @@ -220,7 +219,7 @@ ]) ; Maybe monad -(defmonad maybe +(defmonad maybe-m "Monad describing computations with possible failures. Failure is represented by nil, any other value is considered valid. As soon as a step returns nil, the whole computation will yield nil as well." @@ -233,7 +232,7 @@ ]) ; Sequence monad (called "list monad" in Haskell) -(defmonad sequence +(defmonad sequence-m "Monad describing multi-valued computations, i.e. computations that can yield multiple values. Any object implementing the seq protocol can be used as a monadic value." @@ -247,7 +246,7 @@ ]) ; State monad -(defmonad state +(defmonad state-m "Monad describing stateful computations. The monadic values have the structure (fn [old-state] (list result new-state))." [m-result (fn m-result-state [v] @@ -268,7 +267,7 @@ (update-state identity)) ; Writer monad -(defn writer +(defn writer-m "Monad describing computations that accumulate data on the side, e.g. for logging. The monadic values have the structure [value log]. Any of the accumulators from clojure.contrib.accumulators can be used for storing the @@ -295,7 +294,7 @@ ; Continuation monad -(defmonad cont +(defmonad cont-m "Monad describing computations in continuation-passing style. The monadic values are functions that are called with a single argument representing the continuation of the computation, to which they pass their result." diff --git a/src/clojure/contrib/monads/examples.clj b/src/clojure/contrib/monads/examples.clj index 54748d74..7c11fbc2 100644 --- a/src/clojure/contrib/monads/examples.clj +++ b/src/clojure/contrib/monads/examples.clj @@ -25,19 +25,19 @@ ; Monad comprehensions in the sequence monad work exactly the same ; as Clojure's 'for' construct, except that :while clauses are not ; available. -(domonad sequence +(domonad sequence-m [x (range 5) y (range 3)] (+ x y)) ; Inside a with-monad block, domonad is used without the monad name. -(with-monad sequence +(with-monad sequence-m (domonad [x (range 5) y (range 3)] (+ x y))) -(domonad sequence +(domonad sequence-m [x (range 5) y (range (+ 1 x)) :when (= (+ x y) 2)] @@ -45,7 +45,7 @@ ; An example of a sequence function defined in terms of a lift operation. ; We use m-lift2 because we have to lift a function of two arguments. -(with-monad sequence +(with-monad sequence-m (defn pairs [xs] ((m-lift 2 #(list %1 %2)) xs xs))) @@ -55,14 +55,14 @@ ; a sequence of monadic values and returns a monadic value containing ; the sequence of the underlying values, obtained from chaining together ; from left to right the monadic values in the sequence. -(with-monad sequence +(with-monad sequence-m (defn pairs [xs] (m-seq (list xs xs)))) (pairs (range 5)) ; This definition suggests a generalization: -(with-monad sequence +(with-monad sequence-m (defn ntuples [n xs] (m-seq (replicate n xs)))) @@ -70,13 +70,13 @@ (ntuples 3 (range 5)) ; Lift operations can also be used inside a monad comprehension: -(domonad sequence +(domonad sequence-m [x ((m-lift 1 (partial * 2)) (range 5)) y (range 2)] [x y]) ; The m-plus operation does concatenation in the sequence monad. -(domonad sequence +(domonad sequence-m [x ((m-lift 2 +) (range 5) (range 3)) y (m-plus (range 2) '(10 11))] [x y]) @@ -89,7 +89,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Maybe monad versions of basic arithmetic -(with-monad maybe +(with-monad maybe-m (def m+ (m-lift 2 +)) (def m- (m-lift 2 -)) (def m* (m-lift 2 *))) @@ -99,7 +99,7 @@ ; is attempted. It is best defined by a monad comprehension with a ; :when clause: (defn safe-div [x y] - (domonad maybe + (domonad maybe-m [a x b y :when (not (zero? b))] @@ -107,7 +107,7 @@ ; Now do some non-trivial computation with division ; It fails for (1) x = 0, (2) y = 0 or (3) y = -x. -(with-monad maybe +(with-monad maybe-m (defn some-function [x y] (let [one (m-result 1)] (safe-div one (m+ (safe-div one (m-result x)) @@ -121,7 +121,7 @@ ; In the maybe monad, m-plus selects the first monadic value that ; holds a valid value. -(with-monad maybe +(with-monad maybe-m (m-plus (some-function 2 0) (some-function 2 -2) (some-function 2 3))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -185,7 +185,7 @@ ; In the first version, we call rng 12 times explicitly and calculate the ; shifted sum in a monad comprehension: (def gaussian1 - (domonad state + (domonad state-m [x1 rng x2 rng x3 rng @@ -211,7 +211,7 @@ ; More precisely, we need (m-lift 2 +), because we want both arguments ; of + to be lifted to the state monad: (def gaussian2 - (domonad state + (domonad state-m [sum12 (reduce (m-lift 2 +) (replicate 12 rng))] (- sum12 6.))) @@ -222,7 +222,7 @@ ; We can also do the subtraction of 6 in a lifted function, and get rid ; of the monad comprehension altogether: -(with-monad state +(with-monad state-m (def gaussian3 ((m-lift 1 #(- % 6.)) (reduce (m-lift 2 +) (replicate 12 rng))))) @@ -234,7 +234,7 @@ ; For a random point in two dimensions, we'd like a random number generator ; that yields a list of two random numbers. The m-seq operation can easily ; provide it: -(with-monad state +(with-monad state-m (def rng2 (m-seq (list rng rng)))) ; Let's test it: @@ -243,7 +243,7 @@ ; fetch-state and get-state can be used to save the seed of the random ; number generator and go back to that saved seed later on: (def identical-random-seqs - (domonad state + (domonad state-m [seed (fetch-state) x1 rng x2 rng @@ -261,7 +261,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; A basic logging example -(domonad (writer accu/empty-string) +(domonad (writer-m accu/empty-string) [x (m-result 1) _ (write "first step\n") y (m-result 2) @@ -292,7 +292,7 @@ ; vector accumulator. We can then place calls to write in between the ; steps, and obtain as a result both the return value of the function ; and the accumulated trace values. -(with-monad (writer accu/empty-vector) +(with-monad (writer-m accu/empty-vector) (defn fib-trace [n] (if (< n 2) @@ -329,20 +329,20 @@ ; lead immediately to a nil result in the output. ; First we define the combined monad: -(def seq-maybe (maybe-t sequence)) +(def seq-maybe-m (maybe-t sequence-m)) ; 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 +(domonad seq-maybe-m [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 +(with-monad seq-maybe-m (defn pairs-maybe [xs] (m-seq (list xs xs)))) @@ -369,7 +369,7 @@ ; a function that behaves in the same way, passing 3 to its function ; argument. run-cont executes a continuation by calling it on identity. (run-cont - (domonad cont + (domonad cont-m [x (m-result 1) y (m-result 2)] (+ x y))) @@ -381,7 +381,7 @@ (def continuation nil) (run-cont - (domonad cont + (domonad cont-m [x (m-result 1) y (call-cc (fn [c] (def continuation c) (c 2)))] (+ x y))) @@ -397,7 +397,7 @@ (defn sqrt-as-str [x] (call-cc (fn [k] - (domonad cont + (domonad cont-m [_ (m-when (< x 0) (k (str "negative argument " x)))] (str (. Math sqrt x)))))) diff --git a/src/clojure/contrib/monads/test.clj b/src/clojure/contrib/monads/test.clj index 661fd2a4..8731b940 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 January 12, 2009 +;; last updated February 18, 2009 ;; Copyright (c) Konrad Hinsen, 2008. All rights reserved. The use ;; and distribution terms for this software are covered by the Eclipse @@ -17,7 +17,7 @@ clojure.contrib.macros)) (deftest sequence-monad - (with-monad sequence + (with-monad sequence-m (are (= _1 _2) (domonad [x (range 3) y (range 2)] (+ x y)) '(0 1 1 2 2 3) @@ -33,7 +33,7 @@ '(0 1 2 0 1)))) (deftest maybe-monad - (with-monad maybe + (with-monad maybe-m (let [m+ (m-lift 2 +) mdiv (fn [x y] (domonad [a x b y :when (not (zero? b))] (/ a b)))] (are (= _1 _2) @@ -47,7 +47,7 @@ (m-result 1))))) (deftest seq-maybe-monad - (with-monad (maybe-t sequence) + (with-monad (maybe-t sequence-m) (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))) diff --git a/src/clojure/contrib/probabilities/dist.clj b/src/clojure/contrib/probabilities/dist.clj index 4f9100fd..4c1d321f 100644 --- a/src/clojure/contrib/probabilities/dist.clj +++ b/src/clojure/contrib/probabilities/dist.clj @@ -1,7 +1,7 @@ ;; Finite probability distributions ;; by Konrad Hinsen -;; last updated January 30, 2009 +;; last updated February 18, 2009 ;; Copyright (c) Konrad Hinsen, 2009. All rights reserved. The use ;; and distribution terms for this software are covered by the Eclipse @@ -12,7 +12,6 @@ ;; remove this notice, or any other, from this software. (ns clojure.contrib.probabilities.dist - (:refer-clojure :exclude (sequence)) (:use clojure.contrib.monads clojure.contrib.macros clojure.contrib.monads clojure.contrib.def)) @@ -20,12 +19,12 @@ ; distributions (e.g. there is a finite number of possible value), which ; are represented as maps from values to probabilities. -(defmonad dist +(defmonad dist-m "Monad describing computations on fuzzy quantities, represented by a finite probability distribution for the possible values. A distribution is represented by a map from values to probabilities." [m-result (fn m-result-dist [v] - {v 1}) + {v 1}) m-bind (fn m-bind-dist [mv f] (letfn [add-prob [dist [x p]] (assoc dist x (+ (get dist x 0) p))] @@ -40,8 +39,8 @@ ; The function normalize takes this probability out of the distribution and ; re-distributes its weight over the valid values. -(defvar cond-dist - (maybe-t dist) +(defvar cond-dist-m + (maybe-t dist-m) "Variant of the dist monad that can handle undefined values.") ; Normalization @@ -100,7 +99,7 @@ :else (assoc dist v p))] (reduce add-choice {} (partition 2 choices)))) -(with-monad dist +(with-monad dist-m (defn certainly "Returns a distribution in which the single value v has probability 1." @@ -119,7 +118,7 @@ the predicate pred." [pred dist] (normalize-cond - (with-monad cond-dist + (with-monad cond-dist-m (m-bind dist (fn [v] (m-result (when (pred v) v))))))) ; Select (with equal probability) N items from a sequence @@ -130,7 +129,7 @@ (let [[h t] (split-at n xs)] (list (first t) (concat h (rest t))))) -(with-monad dist +(with-monad dist-m (defn- select-n [n xs] (letfn [select-1 [[s xs]] diff --git a/src/clojure/contrib/probabilities/dist/examples.clj b/src/clojure/contrib/probabilities/dist/examples.clj index 6fb1b5be..947f5366 100644 --- a/src/clojure/contrib/probabilities/dist/examples.clj +++ b/src/clojure/contrib/probabilities/dist/examples.clj @@ -27,13 +27,13 @@ ; The sum of two dice using a monad comprehension (assert (= two-dice - (domonad dist + (domonad dist-m [d1 die d2 die] (+ d1 d2)))) ; The two values separately, but as an ordered pair -(domonad dist +(domonad dist-m [d1 die d2 die] (if (< d1 d2) (list d1 d2) (list d2 d1))) @@ -42,7 +42,7 @@ (cond-prob odd? two-dice) ; A two-step experiment: throw a die, and then add 1 with probability 1/2 -(domonad dist +(domonad dist-m [d die x (choose (/ 1 2) d :else (inc d))] @@ -50,7 +50,7 @@ ; The sum of n dice (defn dice [n] - (domonad dist + (domonad dist-m [ds (m-seq (replicate n die))] (apply + ds))) @@ -84,7 +84,7 @@ (def doors #{:A :B :C}) ; A simulation of the game, step by step: -(domonad dist +(domonad dist-m [; The prize is hidden behind one of the doors. prize (uniform doors) ; The player make his initial choice. @@ -126,7 +126,7 @@ ; Multiple evolution steps can be chained together with m-chain, ; since each step's input is the output of the previous step. -(with-monad dist +(with-monad dist-m (defn evolve [n tree] ((m-chain (replicate n evolve-1)) tree))) @@ -136,7 +136,7 @@ (evolve 2 new-tree) ; We can also get a distribution of the height only: -(with-monad dist +(with-monad dist-m ((m-lift 1 :height) (evolve 2 new-tree))) @@ -170,7 +170,7 @@ ; 4) Normalize the distribution for the non-nil values. (defn add-observation [prior observation] (normalize-cond - (domonad cond-dist + (domonad cond-dist-m [die prior number (get dice die)] (when (= number observation) die)))) @@ -188,7 +188,7 @@ ; With Bayesian inference, it is most efficient to eliminate choices ; as early as possible. (defn add-observations [prior observations] - (with-monad cond-dist + (with-monad cond-dist-m (let [n-nums #(m-seq (replicate (count observations) (get dice %)))] (normalize-cond (domonad |