Lambda Calculus
More restraint and more pure,
so functional and so reduced.-- Anonymous Bauhaus Student
An implementation of (Untyped) Lambda Calculus in JavaScript.
- Use S-expression as overall syntax.
- Implement call-by-need lazy evaluation.
- Allow recursive definitions.
- A simple module system with only one API --
(import)
.- It can import module from local file or remote URL.
- Two simple testing statements
(assert-equal)
and(assert-not-equal)
.- They can handle beta and eta equivalence.
Usage
Online playground
Visit the Lambda Playground.
Command line tool
Install it by the following command:
npm -g i @cicada-lang/lambda
The command line program is called lambda
.
Run a module by file:
lambda docs/tests/nat-church.md
Run a module by URL:
lambda https://readonly.link/files/cicada-lang/lambda/-/docs/tests/nat-church.md
Examples
Please see docs/tests for more examples.
Boolean
[ PLAYGROUND ]
(define (true t f) t)
(define (false t f) f)
(define (if p t f) (p t f))
(define (and x y) (if x y false))
(define (or x y) (if x true y))
(define (not x) (if x false true))
(and true false)
(not (not (or true false)))
Natural Number by Church encoding
[ PLAYGROUND | WIKIPEDIA ]
(define zero (lambda (base step) base))
(define (add1 n) (lambda (base step) (step (n base step))))
(define (iter-Nat n base step) (n base step))
(define one (add1 zero))
(define two (add1 one))
(define three (add1 two))
(define (add m n) (iter-Nat m n add1))
(add two two)
Factorial
[ PLAYGROUND ]
(import "https://readonly.link/files/cicada-lang/lambda/-/docs/tests/nat-church.md"
zero? add mul sub1
zero one two three four)
(import "https://readonly.link/files/cicada-lang/lambda/-/docs/tests/boolean.md"
true false if)
(define (factorial n)
(if (zero? n)
one
(mul n (factorial (sub1 n)))))
(factorial zero)
(factorial one)
(factorial two)
(factorial three)
Factorial by fixpoint combinator
[ PLAYGROUND | WIKIPEDIA ]
(import "https://readonly.link/files/cicada-lang/lambda/-/docs/tests/nat-church.md"
zero? add mul sub1
zero one two three four)
(import "https://readonly.link/files/cicada-lang/lambda/-/docs/tests/boolean.md"
true false if)
;; NOTE `x` is `f`'s fixpoint if `(f x) = x`
;; In lambda calculus, we have function `fix`
;; which can find fixpoint of any function.
;; (f (fix f)) = (fix f)
;; The following `fix` is one way of defining `fix`.
(define (fix f)
((lambda (x) (f (x x)))
(lambda (x) (f (x x)))))
;; (claim factorial-wrap (-> (-> Nat Nat) (-> Nat Nat)))
;; (claim (fix factorial-wrap) (-> Nat Nat))
;; (claim fix (forall (A) (-> (-> A A) A)))
(define (factorial-wrap factorial)
(lambda (n)
(if (zero? n)
one
(mul n (factorial (sub1 n))))))
(define factorial (fix factorial-wrap))
(factorial zero)
(factorial one)
(factorial two)
(factorial three)
(factorial four)
Cons the Magnificent
[ PLAYGROUND ]
;; NOTE Temporarily save `car` and `cdr` to a lambda,
;; apply this lambda to a function -- `f`,
;; will apply `f` to the saved `car` and `cdr`
(define (cons car cdr) (lambda (f) (f car cdr)))
(define (car pair) (pair (lambda (car cdr) car)))
(define (cdr pair) (pair (lambda (car cdr) cdr)))
(import "https://readonly.link/files/cicada-lang/lambda/-/docs/tests/boolean.md"
true false)
(define (null f) true)
(define (null? pair) (pair (lambda (car cdr) false)))
Development
npm install // Install dependencies
npm run build // Compile `src/` to `lib/`
npm run watch // Watch the compilation
npm run test // Run test
Contributions
Be polite, do not bring negative emotion to others.
- TODO.md
- STYLE-GUIDE.md
- CODE-OF-CONDUCT.md
- When contributing, add yourself to AUTHORS