The following is a simple implementation of single-output monadic do-notation as Racket syntax. The programmer can choose the monad that goes into the do-notation: because we avoid generics, we can use the Identity monad, for instance.
#lang racket
(require racket/match)
(struct monad
(return bind))
(define List
(monad
(λ (x) (list x))
(λ (xs f) (append-map f xs))))
(define-syntax do
(syntax-rules (<- pure)
[(_ m mexp) mexp]
[(_ m var <- mexp rest ...) ((monad-bind m) mexp (lambda (var) (do m rest ...)))]
[(_ m pure value) ((monad-return m) value)]
))
(do List
i <- (do List
x <- '(3 4)
v <- '(2 7 4)
pure (+ x v))
j <- '(2 3)
pure (* i j))
;; The main limitation here is that this Do-notation only
;; allows unary outputs. Having more would require using lists
;; in an intelligent way.
(match '(3 4) [(list u v) (+ u v)])Tags: Racket.