This repository has been archived by the owner on Dec 5, 2022. It is now read-only.
/
basic-monads.rkt
79 lines (67 loc) · 1.8 KB
/
basic-monads.rkt
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
70
71
72
73
74
75
76
77
78
79
#lang racket/base
(require racket/list
racket/match)
; ! : num -> num
(define (! n)
(cond
[(zero? n)
4]
[else
(define nv (! (sub1 n)))
(printf "! on ~a subcall return ~a\n" n nv)
(* n nv)]))
; !^ : num -> (vector num (listof strs))
(define (!^ n)
(cond
[(zero? n)
(vector 4 empty)]
[else
(match-define (vector nv strs) (!^ (sub1 n)))
(vector (* n nv)
(cons (format "! on ~a subcall return ~a\n" n nv)
strs))]))
; !M : num -> (Debug num)
(struct Debug (val strs))
;; A -> Debug A
(define (Debug-return v)
(Debug v empty))
;; (Debug A) (A -> (Debug B)) -> (Debug B)
(define (Debug-bind da f)
(match-define (Debug a strs-from-da) da)
(match-define (Debug b strs-from-f) (f a))
(Debug b (append strs-from-da
strs-from-f)))
;; String (-> (Debug A)) -> (Debug A)
(define (Debug-add str after)
(Debug-bind (Debug #f (list str))
(λ (_) (after))))
(define (!M n)
(cond
[(zero? n)
(Debug-return 4)]
[else
(Debug-bind
(!M (sub1 n))
(λ (nv)
(Debug-add
(format "! on ~a subcall return ~a\n" n nv)
(λ ()
(Debug-return (* n nv))))))]))
(module+ test
(require rackunit/chk)
(chk (! 4) (* 4 3 2 1))
(let ()
(match-define (vector ans strs) (!^ 4))
(displayln strs)
(chk ans (* 4 3 2 1)))
(let ()
(match-define (Debug ans strs) (!M 4))
(displayln strs)
(chk ans (* 4 3 2 1))))
(define list-return list)
(define (list-bind l f)
(append-map f l))
(module+ test
(list-bind (list-bind (list 3 4 5 8)
(λ (i) (list (add1 i))))
(λ (i) (list (add1 i)))))