monads: Add 'mbegin'.

* guix/monads.scm (mbegin): New macro.
* tests/monads.scm ("mbegin"): New test.
* doc/guix.texi (The Store Monad): Document it.
This commit is contained in:
Ludovic Courtès 2014-10-08 23:35:08 +02:00
parent 2e1bafb034
commit 405a9d4ec9
4 changed files with 40 additions and 1 deletions

View file

@ -38,6 +38,7 @@
(eval . (put 'syntax-parameterize 'scheme-indent-function 1))
(eval . (put 'with-monad 'scheme-indent-function 1))
(eval . (put 'mbegin 'scheme-indent-function 1))
(eval . (put 'mlet* 'scheme-indent-function 2))
(eval . (put 'mlet 'scheme-indent-function 2))
(eval . (put 'run-with-store 'scheme-indent-function 1))

View file

@ -2061,6 +2061,15 @@ Bind the variables @var{var} to the monadic values @var{mval} in
(@pxref{Local Bindings,,, guile, GNU Guile Reference Manual}).
@end deffn
@deffn {Scheme System} mbegin @var{monad} @var{mexp} ...
Bind @var{mexp} and the following monadic expressions in sequence,
returning the result of the last expression.
This is akin to @code{mlet}, except that the return values of the
monadic expressions are ignored. In that sense, it is analogous to
@code{begin}, but applied to monadic expressions.
@end deffn
The interface to the store monad provided by @code{(guix monads)} is as
follows.

View file

@ -38,6 +38,7 @@ (define-module (guix monads)
with-monad
mlet
mlet*
mbegin
lift1 lift2 lift3 lift4 lift5 lift6 lift7 lift
listm
foldm
@ -171,6 +172,19 @@ (define-syntax mlet
(let ((var temp) ...)
body ...)))))))
(define-syntax mbegin
(syntax-rules ()
"Bind the given monadic expressions in sequence, returning the result of
the last one."
((_ monad mexp)
(with-monad monad
mexp))
((_ monad mexp rest ...)
(with-monad monad
(>>= mexp
(lambda (unused-value)
(mbegin monad rest ...)))))))
(define-syntax define-lift
(syntax-rules ()
((_ liftn (args ...))

View file

@ -32,7 +32,7 @@ (define-module (test-monads)
#:use-module (srfi srfi-26)
#:use-module (srfi srfi-64))
;; Test the (guix store) module.
;; Test the (guix monads) module.
(define %store
(open-connection-for-tests))
@ -99,6 +99,21 @@ (define (g x)
%monads
%monad-run))
(test-assert "mbegin"
(every (lambda (monad run)
(with-monad monad
(let* ((been-there? #f)
(number (mbegin monad
(return 1)
(begin
(set! been-there? #t)
(return 2))
(return 3))))
(and (= (run number) 3)
been-there?))))
%monads
%monad-run))
(test-assert "mlet* + text-file + package-file"
(run-with-store %store
(mlet* %store-monad ((guile (package-file %bootstrap-guile "bin/guile"))