This repository demonstrates compile-time lambda calculus parser, evalator, and type checker in Scala 3. It is heavily depending on match types feature.
Parse[_] returns a type representing an abstract syntax tree of the parsed term.
import lambda.{Parse, Var, Abs, App}
summon[Parse["λx.x"] =:= Abs["x", Var["x"]]]
summon[Parse["λxy.x"] =:= Abs["x", Abs["y", Var["x"]]]]
summon[Parse["x y"] =:= App[Var["x"], Var["y"]]]Eval[_] returns beta-normal form of the specified term. The evaluation strategy is
leftmost-outermost.
import lambda.{Show, Eval, Parse}
summon[Show[Eval[Parse["(λxy.x) a b"]]] =:= "a"]You can also use ReadEvalPrint[_] to Parse and Show together at once.
import lambda.ReadEvalPrint
summon[ReadEvalPrint["(λxy.x) a b"] =:= "a"]Type.Infer[_] returns a (Scala) type representing an abstract syntax tree of the type
(of simply typed lambda calculus) of the specified term.
import lambda.Parse
import typing.{Show, Type}
summon[Show[Type.Infer[Parse["λx.x"]]] =:= "a -> a"]You can also use Type.Check[_] (returns a boolean literal type) to determine whether a
term is typeable.
- tarao/lambda-scala: Type level lambda calculus in Scala
- Scala 2 implmentation of type-level lambda calculus
- It has no type checker
- About type-level lambda calculus in C++03 templates (in Japanese)
- source code
- lambda-scala3 is a translation from this implementation (except the parser)
- About match types and compile-time string literals by @xuwei-k (in Japanese)
- source code 1
- source code 2
- This taught me how to write a compile-time parser