An untyped lambda calculus parser, evaluator, and REPL, written in Haskell.
The REPL can be invoked with either docker
or stack
.
docker build -t lambda-calculus .
docker run -it lambda-calculus
stack build
stack exec lambda-calculus-exe
let {var} = {expr}
λ> let q = λx.x
q := λx.x
λ> let y = (λxyz.xz(yz))(λx.z)(λx.a)
y := (λx.λy.λz.xz(yz))(λx.z)(λx.a)
?
λ> ?
y := (λx.λy.λz.xz(yz))(λx.z)(λx.a)
q := λx.x
! {expr}
λ> ! (λxyz.xz(yz))(λx.z)(λx.a)
λw.za
λ> let y = (λxyz.xz(yz))(λx.z)(λx.a)
λ> ! y
λw.za
trace {expr}
λ> trace (λxyz.xz(yz))(λx.z)(λx.a)
Γ, a, z, (λx.λy.λz.xz(yz))(λx.z)(λx.a)
--------------------------------------
(λx.λy.λz.xz(yz))(λx.z)(λx.a)
-----------------------------
(λy.λw.(λx.z)w(yw))(λx.a)
-------------------------
λw.(λx.z)w((λx.a)w)
-------------------
λw.z((λx.a)w)
-------------
λw.za
(evaluate to β-normal-form and check α-equivalence)
= {expr} {expr}
λ> let z = λx.x
λ> let y = λq.q
λ> = z y
True
via α?.β
λx.x
λq.q
λ> let z = (λz.z)(λz.zz)(λz.zy)
λ> let w = (λx.λy.xyy)(λy.y)y
λ> = z w
True
via α?.β
yy
yy
fv {expr}
λ> fv (λxyz.xz(yz))(λx.z)(λx.a)
{a,z}