-
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
-- Simple untyped lambda calculus interpreter using de Bruijin indices
-- WRONG: https://jameshfisher.com/2018/03/15/a-lambda-calculus-interpreter-in-haskell/
inductive Term where
| A : Term → Term → Term
| L : Term → Term
| V : Nat → Term
unsafe def red : Term → Term
| .A fn arg =>
match red fn with
| .L body =>
let rec incr n d
| .A fn arg' => .A (incr n (d + 1) fn) (incr n (d + 1) arg')
| .L body => .L <| incr n (d + 1) body
| .V n' => .V <| if n' > d then n + n' else n'
let rec sub
| n, .A fn arg' => .A (sub n fn) (sub n arg')
| n, .L body => .L <| sub (n + 1) body
| n, .V n' => if n = n' then incr n 0 arg else .V n'
red <| sub 0 body
| other => .A other arg
| other => other
def I := Term.L (.V 0)
def K := Term.L <| Term.L (.V 1)
def S := Term.L
(.L
(.L
(.A
(.A (.V 2) (.V 0))
(.A (.V 1) (.V 0))
)
)
)
def Y := Term.L
(.A
(.L
(.A (.V 1) (.A (.V 0) (.V 0)))
)
(.L
(.A (.V 1) (.A (.V 0) (.V 0)))
)
)
#eval red <| .A (.A (.A S K) I) (.A (.A K I) S)
#eval red <| .A (.A (.A S K) I) K
-- Doesn't terminate
-- #eval red <| .A Y I