simple let-like monad notation added by alicemaz on Fri Apr 10 06:12:48 2020
(module let-monad-test *
(import scheme)
(import chicken.base)
#| these are all equivalent
(let/m <maybe>
((a (return 1))
(b (return (+ a 1))))
(return (* b 2)))
do a <- return 1
b <- return $ a + 1
return $ b * 2
(>>= (return 1) (lambda (a)
(return (+ a 1)) (lambda (b)
(return (* b 2)))))
|#
(define (just? v) (and (list? v) (not (null? v)) (eq? (car v) 'Just)))
(define (nothing? v) (eq? v 'Nothing))
(define (<maybe>-return v) `(Just ,v))
(define (<maybe>-bind v f) (if (eq? v 'Nothing) 'Nothing (f (cadr v))))
(define (<maybe>-fail) 'Nothing)
(define-syntax let/m
(er-macro-transformer (lambda (e r c)
(let* ((m (cadr e))
(return (symbol-append m '-return))
(bind (symbol-append m '-bind))
(fail (symbol-append m '-fail)))
`(let ((return ,return) (bind ,bind) (fail ,fail)) (let-monad ,@(cddr e)))))))
(define-syntax let-monad
(syntax-rules ()
((let-monad () body1 body2 ...)
(let () body1 body2 ...))
((let-monad ((name1 val1) (name2 val2) ...) body1 body2 ...)
(bind val1 (lambda (name1) (let-monad ((name2 val2) ...) body1 body2 ...))))))
)