blob: 015fc90729d0fba3425680511b9092af2c4107d5 (
plain)
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
|
(define-module (monad optional)
#:use-module (oop goops)
#:use-module (ice-9 match)
#:use-module (monad)
#:use-module (ice-9 curried-definitions)
#:export (from-just wrap-maybe
nothing just
nothing? just?)
#:re-export (>>= >> return))
(define-class <optional> ()
(slot #:init-value #f
#:init-keyword #:slot)
(just #:init-value #t
#:init-keyword #:just))
(define (nothing) (make <optional> #:just #f))
(define (just obj) (make <optional>
#:just #t
#:slot obj))
(define (nothing? this)
(not (slot-ref this 'just)))
(define (just? this)
(not (nothing? this)))
(define (from-just default maybe-val)
"Returns default if maybe-val is nothing, otherwise
the value embedded in maybe-val"
(if (just? maybe-val)
(slot-ref maybe-val 'slot)
default))
(define ((wrap-maybe proc) . values)
"Wraps a function in an optional monad, where #f returns are translated to nothing."
(let ((v (apply proc values)))
(if v (just v) (nothing))))
(define-method (write (this <optional>) port)
(if (just? this)
(format port "[Just ~s]" (slot-ref this 'slot))
(format port "[Nothing]")))
(define-method (>>= (this <optional>)
(proc <procedure>))
(cond ((nothing? this) (nothing))
((just? this)
(match this
(($ <optional> slot) (proc slot))))))
(define-method (return (a <optional>)) just)
(define-method (equal? (a <optional>)
(b <optional>))
(or (and (nothing? a) (nothing? b))
(from-just #f (do aa <- a
bb <- b
(just (equal? aa bb))))))
|