Created
October 17, 2023 19:21
-
-
Save kmicinski/f2815647fcc0e43ed3599e8639e64097 to your computer and use it in GitHub Desktop.
Lambda calculus basics
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#lang racket | |
;; λ-calculus expressions | |
(define (expr? e) | |
(match e | |
[(? symbol? x) #t] ;; variables | |
[`(λ (,(? symbol? x)) ,(? expr? e-body)) #t] ;; λ abstractions | |
[`(,(? expr? e-f) ,(? expr? e-a)) #t] ;; applications | |
[_ #f])) | |
;; Example λ-calculus terms | |
(expr? '((λ (x) (x x)) y)) | |
(expr? '(λ (z) (z (y x)))) | |
(expr? '(x z)) | |
(expr? '((x ((λ (x) x) x)) (y (λ (z) z)))) | |
;; Here are three applications, which of the following are | |
;; β redexes ("i.e., β-reducible expression"): | |
'(x (λ (y) y)) ;; no | |
'((x y) (y (λ (z) z))) ;; no | |
'((λ (x) (x x)) (λ (z) z)) ;; yes | |
;; E0 is (x x) and E1 is (λ (z) z) | |
;; Thus, it β-reduces to... | |
;; →β E0 [ x ↦ E1 ] | |
;; = (x x) [ x ↦ (λ (z) z) ] | |
'((λ (z) z) (λ (z) z)) | |
(define (substitute E0 x E1) 'todo) | |
(define (apply-β e) | |
(match e | |
[`((lambda (,x) ,E0) ,E1) | |
;; have to define substitute | |
(substitute E0 x E1)])) | |
;; β reduce the following | |
;; I mean: take the top-level application and perform | |
;; "one step" of β reduction for the term | |
;; Example 1 | |
;;'((λ (x) (x (x y))) (λ (z) (z x))) | |
;; By the definition of β reduction | |
;;-->β (x (x y)) [ x ↦ (λ (z) (z x)) ] | |
;; (e1) = ((λ (z) (z x)) ((λ (z) (z x)) y)) | |
;; | |
;; Now, we have two possibilities for β reduction | |
;; We will see that when you get to a application, you have of two options | |
;; - You can either use the "applicative" order and | |
;; "eagerly" reduce the argument until you can't reduce | |
;; any more. This is called the "call by value" approach, because it attempts | |
;; to reduce the arguments of λs down to "values" before the application can | |
;; proceed. | |
;; - Alternatively ("normal" order), you could "lazily" defer reduction of the argument and | |
;; instead apply the function right away. This is the "call by name" approach. | |
;; | |
;; If I take the "normal" order decision, I don't reduce the argument... | |
;; -->β (z x) [z ↦ ((λ (z) (z x)) y) ] | |
;; = (((λ (z) (z x)) y) x) (e2) | |
;; -->β ((y x) x) | |
;; this is in β normal form (i.e., no more possible β reduction) | |
;; | |
;; If instead I take the "applicative" order, I get.. | |
;; ((λ (z) (z x)) (y x)) (e3) | |
;; -->β ((y x) x) | |
;; This is also in β normal form | |
;; Theorem (Church Rosser): if two expressions are equivalent, they give | |
;; the same β normal form. | |
;; If e -->β e' and e -->β e'', then there is some e''' such that | |
;; e' -->* e''' and e'' -->* e''' | |
;; Example 2 | |
((λ (z) (z (z z))) (λ (x) (x x))) | |
;; Three options: | |
;; (1) Every way of β reducing the term will lead to nontermination | |
;; (2) Every way of β reducing the term will lead to termination | |
;; ** (3) Some ways of β reducing will terminate, others will not... | |
((λ (x) (λ (y) y)) | |
((λ (x) (x x)) (λ (x) (x x)))) | |
;; Normal order evaluation / CBN / lazy evaluation gives us... | |
(λ (y) y) ;; which immediately terminates | |
; f(x) = 3 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment