summary refs log tree commit diff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2014-07-12 17:16:36 +0200
committerLudovic Courtès <ludo@gnu.org>2014-07-12 23:17:53 +0200
commitf62435e2868f5db15cc2f31300630c8ec873dd58 (patch)
tree4c48f36fafd1c02b5d65fb92fd257e3bd0c78dc0
parentc2150d9acece1dcaf54b3183254db4f83a992523 (diff)
downloadguix-f62435e2868f5db15cc2f31300630c8ec873dd58.tar.gz
monads: Fix 'mapm' so that effects happen from left to right.
* guix/monads.scm (mapm): Don't reverse LST, so that items are processed
  from left to right.  Bind the result of 'foldm' and reverse it.
* tests/monads.scm ("sequence"): Change 'frob' so it performs its side
  effect within an 'mlet' body.  Adjust call accordingly.
-rw-r--r--guix/monads.scm16
-rw-r--r--tests/monads.scm14
2 files changed, 17 insertions, 13 deletions
diff --git a/guix/monads.scm b/guix/monads.scm
index ec2b7f8b3b..c2c6f1a03d 100644
--- a/guix/monads.scm
+++ b/guix/monads.scm
@@ -209,13 +209,15 @@ monadic value seeded by INIT."
 
 (define (mapm monad mproc lst)
   "Map MPROC over LST, a list of monadic values in MONAD, and return a monadic
-list."
-  (foldm monad
-         (lambda (item result)
-           (mlet monad ((item (mproc item)))
-             (return (cons item result))))
-         '()
-         (reverse lst)))
+list.  LST items are bound from left to right, so effects in MONAD are known
+to happen in that order."
+  (mlet monad ((result (foldm monad
+                              (lambda (item result)
+                                (mlet monad ((item (mproc item)))
+                                  (return (cons item result))))
+                              '()
+                              lst)))
+    (return (reverse result))))
 
 (define-inlinable (sequence monad lst)
   "Turn the list of monadic values LST into a monadic list of values, by
diff --git a/tests/monads.scm b/tests/monads.scm
index 82f4b9989c..ac19d33f93 100644
--- a/tests/monads.scm
+++ b/tests/monads.scm
@@ -166,14 +166,16 @@
            (let* ((input (iota 100))
                   (order '()))
              (define (frob i)
-               ;; The side effect here is used to keep track of the order in
-               ;; which monadic values are bound.
-               (set! order (cons i order))
-               i)
+               (mlet monad ((foo (return 'foo)))
+                 ;; The side effect here is used to keep track of the order in
+                 ;; which monadic values are bound.  Perform the side effect
+                 ;; within a '>>=' so that it is performed when the return
+                 ;; value is actually bound.
+                 (set! order (cons i order))
+                 (return i)))
 
              (and (equal? input
-                          (run (sequence monad
-                                         (map (lift1 frob monad) input))))
+                          (run (sequence monad (map frob input))))
 
                   ;; Make sure this is from left to right.
                   (equal? order (reverse input)))))