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.
This commit is contained in:
Ludovic Courtès 2014-07-12 17:16:36 +02:00
parent c2150d9ace
commit f62435e286
2 changed files with 17 additions and 13 deletions

View File

@ -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

View File

@ -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)))))