(module monad * (import scheme chicken extras srfi-1) (define-syntax define-monad (lambda (f r c) (##sys#check-syntax 'define-monad f '(_ _ _ . _)) (let* ((name (cadr f)) (unit-function (caddr f)) (bind-function (cadddr f)) (rest (cddddr f)) (fail-function (if (null? rest) `(case-lambda (() (error (format "Failure in evaluating ~S monad." ',name))) ((_ . _) (error (format "Failure in evaluating ~S monad." ',name)))) (car rest))) (bindf (symbol-append name '-bind)) (unitf (symbol-append name '-unit)) (failf (symbol-append name '-fail))) `(begin (,(r 'define) ,unitf ,unit-function) (,(r 'define) ,bindf ,bind-function) (,(r 'define) ,failf ,fail-function))))) (define-syntax using (lambda (f r c) (##sys#check-syntax 'using f '(_ _ . _)) (let* ((name (cadr f)) (body (cddr f))) `(,(r 'let) ((>>= ,(symbol-append name '-bind)) (return ,(symbol-append name '-unit)) (fail ,(symbol-append name '-fail))) (define-syntax /m (lambda (f r c) (let* ((f* (symbol-append ',name '- (cadr f)))) f*))) (define-syntax /m! (lambda (f r c) (let* ((f* (symbol-append ',name '- (cadr f))) (rest (cddr f))) `(,f* . ,rest)))) ,@body)))) (define-syntax fail (lambda (f r c) (##sys#check-syntax 'return f '(_ _ . _)) (let* ((name (cadr f)) (body (cddr f))) `(,(symbol-append name '-fail) ,@body)))) (define-syntax return (lambda (f r c) (##sys#check-syntax 'return f '(_ _ . _)) (let* ((name (cadr f)) (body (cddr f))) `(,(symbol-append name '-unit) ,@body)))) (define-syntax do-using (lambda (f r c) (letrec ((name (cadr f)) (body (cddr f)) (bindf (symbol-append name '-bind)) (unitf (symbol-append name '-unit)) (failf (symbol-append name '-fail)) (name- (symbol-append name '-))) `((,(r 'lambda) () (define return ,unitf) (define fail ,failf) (define >>= ,bindf) (define-syntax /m (lambda (f r c) (let* ((f* (symbol-append ',name '- (cadr f)))) f*))) (define-syntax /m! (lambda (f r c) (let* ((f* (symbol-append ',name '- (cadr f))) (rest (cddr f))) `(,f* . ,rest)))) (define-syntax bound-do (syntax-rules (<-) ((_ m) m) ((_ (var <- m) m* m** ...) (,bindf m (lambda (var) (bound-do m* m** ...)))) ((_ m m* m** ...) (,bindf m (lambda (_) (bound-do m* m** ...)))))) (bound-do ,@body)))))) (define-syntax do (syntax-rules () ((do m ...) (do-using m ...)))) (define-monad (lambda (a) a) (lambda (a f) (f a))) (define-monad (lambda (a) `(Just ,a)) (lambda (a f) (if (not (eq? 'Nothing a)) (f a) 'Nothing)) (case-lambda (() 'Nothing) ((_ . _) 'Nothing))) (define-monad (lambda (a) (list a)) (lambda (a f) (concatenate (map f a)))) (define-monad (lambda (a) (lambda (s) `(,a . ,s))) (lambda (a f) (lambda (s) (let* ((p (a s)) (a^ (car p)) (s^ (cdr p))) ((f a^) s^))))) (define (-get s) `(,s . ,s)) (define (-put new-state) (lambda (s) `(() . ,new-state))) (define (-gets f) (do-using (s <- (/m get)) (return (f s)))) (define (-modify f) (do-using (s <- (/m get)) (/m! put (f s)))) (define-monad (lambda (a) (lambda (v) a)) (lambda (a f) (lambda (v) ((f (a v)) v)))) (define (-ask a) a) (define (-asks f) (do-using (x <- (/m ask)) (return (f x)))) (define (-local f r) (lambda (a) (r (f a)))) (define-monad (lambda (a) (lambda (k) (k a))) (lambda (a f) (lambda (k) (a (lambda (a^) (let ((b (f a^))) (b k))))))) (define (-call/cc f) (lambda (c) ((f [lambda (a) (lambda () (c a))]) c))) (define-monad (lambda (a) `(success ,a)) (lambda (a f) (if (eq? (car a) 'success) (f (cadr a)) a)) (case-lambda (() `(failure)) ((a . b) `(failure ,a . ,b)))) (define (-throw e) (do-using (/m! fail e))) (define (-catch m f) (if (eq? (car m) 'failure) (f m) m)) (define-monad (lambda (a) `(,a . ())) (lambda (a f) (let* ((b (f (car a)))) `(,(car b) . ,(append (cdr a) (cdr b)))))) (define (-tell v) `(() . ,v)) (define (-listen a) `(,a . ,(cdr a))) (define (-listens f m) (do (pair <- m) (return `(,(car pair) . ,(f (cdr pair)))))) (define (-pass m) ; expects ((v . f) . w) (let* ((p (car m)) (a (car p)) (f (cdr p)) (w (cdr m))) `(,a . ,(f w)))) (define (-censor f m) (-pass (do-using (a <- m) (return `(,a . ,f))))) )