A purely-functional programming language with Hindley-Milner type inference and `callcc`.
Go to file
James T. Martin 59a55acdc6
Make the parser produce a subtly better AST.
This is done by requiring applications to be at least 2 terms,
and making grouping a syntactic feature instead of a feature of applications.

I also made the code a bit more clear by handling whitespace a bit more cleanly;
now, each parser is responsible for its own trailing whitespace,
and whitespace handling is pushed down to the token level
to avoid cluttering high-level definitions with whitespace stuff.

This all also had the effect of improving error messages,
in part due to me labelling many of the parsers.
2020-11-03 15:52:04 -08:00
.github/workflows Add GitHub workflow. 2020-11-02 16:00:43 -08:00
app Make the printer smarter, separate intermediate AST data type. 2020-11-03 13:43:43 -08:00
src Make the parser produce a subtly better AST. 2020-11-03 15:52:04 -08:00
test Make the parser produce a subtly better AST. 2020-11-03 15:52:04 -08:00
.editorconfig Allow defining multiple variables with one `let`. 2020-11-03 11:33:35 -08:00
.gitignore Complexity was getting out of hand. Beginning a rewrite. Added tests. 2019-12-11 18:29:28 -08:00
LICENSE Initial commit. Some terms are still not evaluated correctly. 2019-08-15 10:42:24 -07:00
README.md Make the parser produce a subtly better AST. 2020-11-03 15:52:04 -08:00
Setup.hs Initial commit. Some terms are still not evaluated correctly. 2019-08-15 10:42:24 -07:00
package.yaml Make the parser produce a subtly better AST. 2020-11-03 15:52:04 -08:00
stack.yaml Make the printer smarter, separate intermediate AST data type. 2020-11-03 13:43:43 -08:00
stack.yaml.lock Make the printer smarter, separate intermediate AST data type. 2020-11-03 13:43:43 -08:00

README.md

Lambda Calculus

This is a simple implementation of the untyped lambda calculus with an emphasis on clear, readable Haskell code.

Usage

Type in your expression at the prompt: >> . The expression will be evaluated to normal form and then printed. Exit the prompt with Ctrl-c (or equivalent).

Example session

>> let D = \x. x x; F = \f. f (f y) in D (F \x. x)
y y
>> let T = \f x. f (f x) in (\f x. T (T (T (T T))) f x) (\x. x) y
y
>> (\x y z. x y) y
λy' z. y y'
>> let fix = (\x. x x) \fix f x. f (fix fix f) x; S = \n f x. f (n f x); plus = fix \plus x. x S in plus (\f x. f (f (f x))) (\f x. f (f x)) f x
f (f (f (f (f x))))
>> ^C

Notation

Conventional Lambda Calculus notation applies, with the exception that variable names are multiple characters long, \ is permitted in lieu of λ to make it easier to type, and spaces are used to separate variables rather than commas.

  • Variable names are alphanumeric, beginning with a letter.
  • Outermost parentheses may be dropped: M N is equivalent to (M N).
  • Applications are left-associative: M N P may be written instead of ((M N) P).
  • The body of an abstraction or let expression extends as far right as possible: \x. M N means \x.(M N) and not (\x. M) N.
  • A sequence of abstractions may be contracted: \foo. \bar. \baz. N may be abbreviated as \foo bar baz. N.
  • Variables may be bound using let expressions: let x = N in M is syntactic sugar for (\x. N) M.
  • Multiple variables may be defined in one let expression: let x = N; y = O in M