Browse Source

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.
wip-grafts
Ludovic Courtès 7 years ago
parent
commit
f62435e286
  1. 16
      guix/monads.scm
  2. 14
      tests/monads.scm

16
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

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

Loading…
Cancel
Save