forked from ibawt/chezuv
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmonad.ss
69 lines (61 loc) · 1.85 KB
/
monad.ss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
(define async? procedure?)
(define (make-async task)
(lambda (c)
(let ([ok (lambda (a) (c #f a))]
[fail (lambda (a) (c a #f))])
(task ok fail))))
(define (async-return value)
(make-async
(lambda (ok fail) (ok value))))
(define (async-bind async f)
(make-async
(lambda (ok fail)
(async (lambda (e v)
(if e
(fail e)
((f v) (lambda (ee vv)
(if ee
(fail ee)
(ok vv))))))))))
(define-syntax async-do
(syntax-rules ()
[(_ e ...) (monad-do (async-return async-bind async?) e ... )]))
(define-syntax async-do*
(syntax-rules (<-)
[(_ e) e]
[(_ (<- var e1) e2 ...)
(async-bind e1 (lambda (var) (async-do* e2 ...)))]
[(_ e1 e2 ...)
(async-bind e1 (lambda (_) (async-do* e2 ...)))]))
(define-syntax ->async
(syntax-rules ()
[(_ e)
(let ([e-result e])
(if (async? e-result)
e-result
(async-return e-result)))]))
(define-syntax async-do**
(syntax-rules (<-)
[(_ e)
(->async e)]
[(_ (<- var e1) e2 ...)
(async-bind (->async e1) (lambda (var) (async-do** e2 ...)))]
[(_ e1 e2 ...)
(async-bind (->async e1) (lambda (_) (async-do** e2 ...)))]))
(define-syntax ->monad
(syntax-rules ()
[(_ (return monad?) e)
(let ([e-result e])
(if (monad? e-result)
e-result
(return e-result)))]))
(define-syntax monad-do
(syntax-rules (<-)
[(_ (return >>= monad?) e)
(->monad (return monad?) e)]
[(_ (return >>= monad?) (<- var e1) e2 ...)
(>>= (->monad (return monad?) e1)
(lambda (var) (monad-do (return >>= monad?) e2 ...)))]
[(_ (return >>= monad?) e1 e2 ...)
(>>= (->monad (return monad?) e1)
(lambda (_) (monad-do (return >>= monad?) e2 ...)))]))