lambda.mlish (2149B)
1 #lang s-exp "../../../mlish.rkt" 2 (require "../../rackunit-typechecking.rkt") 3 4 ;; Lambda Calculus interpreter 5 6 7 ;; Problems: 8 ;; - Cannot use variable in head position of match (gotta exhaust constructors) 9 10 ;; ----------------------------------------------------------------------------- 11 12 (define-type Λ 13 (Var Int) 14 (Lambda Int Λ) 15 (App Λ Λ)) 16 17 (define (fresh [e : Λ] → Int) 18 (match e with 19 [Var i -> (+ i 1)] 20 [Lambda i e -> (+ i (fresh e))] 21 [App e1 e2 -> (+ 1 (+ (fresh e1) (fresh e2)))])) 22 23 (define (subst [e : Λ] [i : Int] [v : Λ] → Λ) 24 (match e with 25 [Var j -> 26 (if (= i j) 27 v 28 e)] 29 [Lambda j e2 -> 30 (if (= i j) 31 e 32 (Lambda j (subst e2 i v)))] 33 [App e1 e2 -> 34 (App (subst e1 i v) (subst e2 i v))])) 35 36 (define (simpl-aux [e : Λ] [i : Int] → (× Int Λ)) 37 (match e with 38 [Var j -> (tup i (Var j))] 39 [Lambda j e -> 40 (match (simpl-aux (subst e j (Var i)) (+ i 1)) with 41 [k e2 -> 42 (tup k (Lambda i e2))])] 43 [App e1 e2 -> 44 (match (simpl-aux e1 i) with 45 [j e1 -> 46 (match (simpl-aux e2 j) with 47 [k e2 -> 48 (tup k (App e1 e2))])])])) 49 50 (define (simpl [e : Λ] → Λ) 51 (match (simpl-aux e 0) with 52 [i e2 -> e2])) 53 54 (define (eval [e : Λ] → Λ) 55 (match e with 56 [Var i -> (Var i)] 57 [Lambda i e1 -> e] 58 [App e1 e2 -> 59 (match (eval e1) with 60 [Var i -> (Var -1)] 61 [App e1 e2 -> (Var -2)] 62 [Lambda i e -> 63 (match (tup 0 (eval e2)) with 64 [zero v2 -> 65 (eval (subst e i (subst v2 i (Var (+ (fresh e) (fresh v2))))))])])])) 66 67 ;; ----------------------------------------------------------------------------- 68 69 (define I (Lambda 0 (Var 0))) 70 (define K (Lambda 0 (Lambda 1 (Var 0)))) 71 (define S (Lambda 0 (Lambda 1 (Lambda 2 (App (App (Var 0) (Var 2)) (App (Var 1) (Var 2))))))) 72 (define false (App S K)) 73 74 ;; ----------------------------------------------------------------------------- 75 76 (check-type 77 (eval I) 78 : Λ 79 ⇒ I) 80 81 (check-type 82 (eval (App I I)) 83 : Λ 84 ⇒ I) 85 86 (check-type 87 (eval (App (App K (Var 2)) (Var 3))) 88 : Λ 89 ⇒ (Var 2)) 90 91 (check-type 92 (eval (App (App false (Var 2)) (Var 3))) 93 : Λ 94 ⇒ (Var 3)) 95