-
Notifications
You must be signed in to change notification settings - Fork 0
/
2.06.scm
138 lines (105 loc) · 2.31 KB
/
2.06.scm
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
(define zero
(lambda (f)
(lambda (x) x)))
(define (add-1 n)
(lambda (f)
(lambda (x)
(f ((n f) x)))))
; one を導出するには (add-1 zero) の簡約を行えばよい
(add-1 zero)
(lambda (f)
(lambda (x)
(f ((zero f) x))))
(lambda (f)
(lambda (x)
(f (((lambda (f) (lambda (x) x)) f) x))))
(lambda (f)
(lambda (x)
(f ((lambda (x) x) x))))
(lambda (f)
(lambda (x)
(f x)))
; このように簡約できるので、one の定義は以下の通り
(define one
(lambda (f)
(lambda (x)
(f x))))
; 同様に two の導出には (add-1 one) 行えばよい
(add-1 one)
(lambda (f)
(lambda (x)
(f ((one f) x))))
(lambda (f)
(lambda (x)
(f (((lambda (f) (lambda (x) (f x))) f) x))))
(lambda (f)
(lambda (x)
(f ((lambda (x) (f x)) x))))
(lambda (f)
(lambda (x)
(f (f x))))
; このように簡約できるので、two の定義は以下の通り
(define two
(lambda (f)
(lambda (x)
(f (f x)))))
; ここまでの結果から、次のことが見えてくる
;
; zero => f の評価が0回
; one => f の評価が1回
; two => f の評価が2回
;
; よって、+演算子は f の評価を重ねるように実装すればよさそう
(define (add n1 n2)
(lambda (f)
(lambda (x)
((n2 f) ((n1 f) x)))))
; 1 + 2 を簡約しこの定義が正しいかテストする
(add one two)
(lambda (f)
(lambda (x)
((two f) ((one f) x))))
(lambda (f)
(lambda (x)
((two f) (((lambda (f)
(lambda (x)
(f x)))
f) x))))
(lambda (f)
(lambda (x)
((two f) ((lambda (x)
(f x))
x))))
(lambda (f)
(lambda (x)
((two f) (f x))))
(lambda (f)
(lambda (x)
(((lambda (f)
(lambda (x)
(f (f x))))
f) (f x))))
(lambda (f)
(lambda (x)
((lambda (x)
(f (f x)))
(f x))))
(lambda (f)
(lambda (x)
(f (f (f x)))))
; f の評価が3回の手続きに簡約できた
(define (lambda->int f)
((f (lambda (x) (+ x 1))) 0))
(define (print-lambda f)
(print (lambda->int f)))
; おまけ 掛け算
(define (sub n m)
(lambda (f)
(lambda (x)
((m (n f)) x))))
(define (main args)
(print-lambda one)
(print-lambda two)
(print-lambda (add one two))
(print-lambda (sub (add one two) (add two two)))
)