summaryrefslogtreecommitdiff
path: root/guix/monads.scm
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2015-06-08 22:49:50 +0200
committerLudovic Courtès <ludo@gnu.org>2015-06-08 23:00:49 +0200
commit751630c9c3f7f3e87dfccc5f5ba8cf61cdd6f8fd (patch)
tree2da2fcf7e6e300c98f2777e0bcb5670252ff4803 /guix/monads.scm
parentae9b96c7846cc7d4528da5c6d861d6440cf46e33 (diff)
downloadgnu-guix-751630c9c3f7f3e87dfccc5f5ba8cf61cdd6f8fd.tar
gnu-guix-751630c9c3f7f3e87dfccc5f5ba8cf61cdd6f8fd.tar.gz
monads: Allow n-ary '>>=' expressions.
Suggested by Federico Beffa <beffa@fbengineering.ch>. * guix/monads.scm (bind-syntax): New macro. (with-monad): Use it instead of 'identifier-syntax'. * tests/monads.scm (">>= with more than two arguments"): New test. * doc/guix.texi (The Store Monad): Explain that there can be several MPROC. Add an example.
Diffstat (limited to 'guix/monads.scm')
-rw-r--r--guix/monads.scm27
1 files changed, 25 insertions, 2 deletions
diff --git a/guix/monads.scm b/guix/monads.scm
index 4248525433..2196a9c991 100644
--- a/guix/monads.scm
+++ b/guix/monads.scm
@@ -112,6 +112,29 @@
(lambda (s)
(syntax-violation 'return "return used outside of 'with-monad'" s)))
+(define-syntax-rule (bind-syntax bind)
+ "Return a macro transformer that handles the expansion of '>>=' expressions
+using BIND as the binary bind operator.
+
+This macro exists to allow the expansion of n-ary '>>=' expressions, even
+though BIND is simply binary, as in:
+
+ (with-monad %state-monad
+ (>>= (return 1)
+ (lift 1+ %state-monad)
+ (lift 1+ %state-monad)))
+"
+ (lambda (stx)
+ (define (expand body)
+ (syntax-case body ()
+ ((_ mval mproc)
+ #'(bind mval mproc))
+ ((x mval mproc0 mprocs (... ...))
+ (expand #'(>>= (>>= mval mproc0)
+ mprocs (... ...))))))
+
+ (expand stx)))
+
(define-syntax with-monad
(lambda (s)
"Evaluate BODY in the context of MONAD, and return its result."
@@ -120,13 +143,13 @@
(eq? 'macro (syntax-local-binding #'monad))
;; MONAD is a syntax transformer, so we can obtain the bind and return
;; methods by directly querying it.
- #'(syntax-parameterize ((>>= (identifier-syntax (monad %bind)))
+ #'(syntax-parameterize ((>>= (bind-syntax (monad %bind)))
(return (identifier-syntax (monad %return))))
body ...))
((_ monad body ...)
;; MONAD refers to the <monad> record that represents the monad at run
;; time, so use the slow method.
- #'(syntax-parameterize ((>>= (identifier-syntax
+ #'(syntax-parameterize ((>>= (bind-syntax
(monad-bind monad)))
(return (identifier-syntax
(monad-return monad))))