Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.

22
Implementing a Implementing a Dependently Typed Dependently Typed λ λ - - Calculus Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg

Transcript of Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.

Page 1: Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.

Implementing a Implementing a Dependently Typed Dependently Typed λλ--CalculusCalculus

Ali Assaf Abbie DesrosiersAlexandre Tomberg

Page 2: Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.

OutlineOutlineλ-calculus.Implementation strategiesTyped λ-calculusPolymorphic types, System FDependent typesCurrent work

Page 3: Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.

MotivationsMotivationsλ-calculus expresses function

abstractions◦Powerful, Turing-complete.◦Foundation of functional programming

languages.◦Strong connection with logic.

This project:◦Study types◦Explore different implementations

Page 4: Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.

The The λλ-calculus-calculusVery simple language:

◦Terms M = x | λ x . M | M N◦Reductions (λ x . M) N => [N/x] M

Examples◦ Identity: λ x . x ◦Constant function: λ x . λ y . x◦Omega: λ x . (x x)

Page 5: Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.

Implementation strategiesImplementation strategiesExplicit substitution

◦term = var “x” | lam “x” M | app M N◦“Natural way” of representing

lambda expressions.◦Problems :

No immediate α-renaming Free variable capture problem

Page 6: Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.

Implementation strategies Implementation strategies (cont’d)(cont’d)De Bruijn indices

◦term M = Var n | lam M | app M N◦e.g. Identity: λ . 1, Constant: λ . λ . 2◦Advantages:

Unique representation

◦Problems: Not simple to manipulate.

λ x . (λ y . x) x = λ . (λ . 2). 1 Need to shift indices in substitution to avoid

capture.

Page 7: Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.

Implementation strategies Implementation strategies (cont’d)(cont’d)Higher Order Abstract Syntax

(HOAS)◦Use the features of the meta-

language !◦term M = lam f | app M N

where f is a function term → term◦Term substitution :

sub (lam f) N => lam (f N)◦α-renaming already provided!◦WARNING : Leads to ridiculously short

implementations.

Page 8: Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.

Our implementationsOur implementations

De Bruijn in SMLdatatype exp = var of int | lam of exp | app of exp * exp

fun shift (var x) l b = if x > b then var (x + l) else var x

| shift (lam m) l b = lam (shift m l (b + 1))

| shift (app (m, n)) l b = app(shift m l b, shift n l b)

fun sub (var y) s x l =

if y = x then shift s l 0 (* Substitution *)

else if y > x then var (y-1) (* Free variable *)

else var y (* Bound variable *)

| sub (lam m) s x l = lam (sub m s (x + 1) (l + 1))

| sub (app (m, n)) s x l = app (sub m s x l, sub n s x l)

fun eval (var x) = var x

| eval (lam m) = lam (eval m)

| eval (app (m, n)) = case eval m of

lam m' => eval (sub m' n 1 0)

| m' => (app (m', eval n))

HOAS in SMLdatatype exp = lam of (exp -> exp) | app of exp * exp;

fun eval (lam m) = lam (fn x => eval (m x))

| eval (app (m, n)) =

case eval m of

lam m' => eval (m' n)

| m' => app (m', n)

Page 9: Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.

Our implementationsOur implementations

Twelfexp : type.

lam : (exp -> exp) -> exp.

app : exp -> exp -> exp.

eval : exp -> exp -> type.

eval/lam : eval (lam M) (lam M).

eval/app : eval (app M N) N'

<- eval M (lam M')

<- eval (M' N) N'.

SMLdatatype exp = lam of (exp -> exp)

| app of exp * exp;

fun eval (lam m) = lam (fn x => eval (m x))

| eval (app (m, n)) =

case eval m of

lam m' => eval (m' n)

| m' => app (m', n)

Page 10: Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.

The The ωω problem problemConsider the function:

ω = λ x . ( x x )What happens if we apply it to itself?ω ω = (λ x . ( x x )) ω => ω ω => ω ω => ...Evaluation never terminates!

We say (ω ω) doesn’t have a normal form.

To solve this problem, we introduce types.

Page 11: Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.

TypesTypesEach function f has a fixed

domain A and co-domain B (like sets in math).

types τ = a | τ → σwhere a is a base type (e.g. nat)

Typing rules

◦XXXXXXXXXXXXXX

Page 12: Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.

Return of the Return of the ωωWhat happens to ω ?

◦ω = λ x. xxω : α → βx : α, but also x : α → βα ≠ α → β

ω cannot have a valid type!Simply-typed lambda calculus is strongly

normalizing.

Page 13: Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.

Implementing typesImplementing typesMuch easier in Twelf: use HOAS.

This corresponds to Curry style.

t : type.a : t.arrow : t -> t -> t.%infix right 10 arrow.

exp : type.lam : (exp -> exp) -> exp.app : exp -> exp -> exp.

check : exp -> t -> type.check/lam : check (lam M) (A arrow B) <- {x:exp} (check x A -> check (M x) B).check/app : check (app M N) B <- check M (A arrow B) <- check N A.

Page 14: Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.

ExamplesExamplesType checking:

◦ check (lam ([x] x)) (A arrow A)

Secret weapon: we can use Twelf to do type inference !◦ %query 1 * check (lam ([x] x)) T

T = X1 arrow X2 arrow X1.

ω ?◦ %query 1 * check (lam ([x] app x x)) T

Query error -- wrong number of solutions: expected 1 in * tries, but found 0

Page 15: Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.

Another implementationAnother implementationCute trick :

Then ill-typed terms cannot even be constructed !

This corresponds to Church style.

t : type.a : t.arrow : t -> t -> t.%infix right 10 arrow.

exp : t -> type.lam : (exp T1 -> exp T2) -> exp (T1 arrow T2).app : exp (T1 arrow T2) -> exp T1 -> exp T2.

Page 16: Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.

Limitations of simple Limitations of simple typestypesDecidable, but no longer Turing

complete.id = λ x : a . x

id = λ x : b . xid = λ x : nat . xid = λ x : (a → a) . x

We need to write a different identity function for each type.◦To avoid that we need polymorphism.

Page 17: Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.

Polymorphism: System FPolymorphism: System FIdea: Allow abstraction over types.Then, we can write a single

identity function for any type a:Λ a . λ x : a . x

We extend our definition of types and terms:◦τ = a | τ → τ | Π a . τ◦M = x | λ x : τ . M | M N | Λ a . M | M {τ}

Implementations follow the same idea.

Page 18: Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.

Dependent types : LFDependent types : LFIdea: Let types depend on values.Keep information about our types.Examples:

◦Vector : Nat → type.◦Vector n is the type of vectors of length

n.◦Exp t

Advantages:◦We won’t need to prove properties

about our programs !

Page 19: Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.

Current workCurrent workPolymorphic types in TwelfDependent types in TwelfTypes in SML

◦Problems with HOAS.

Page 20: Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.

Problems with HOASProblems with HOASCurrent functional languages (like

SML) present a few problems:◦Do not allow us to look inside functions.◦Hard to generate λ terms.

Solutions:◦ Improve functional programming languages.

Beluga

◦Try different paradigms. Python

Page 21: Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.

Why Python?Why Python?Dynamically typed.Very flexible code generation.User-friendly interface.

I = Lam(lambda x : x)K = Lam(lambda x : Lam (lambda y : x))O = Lam(lambda x : App(x, x))print "I = ", Iprint "K = ", Kprint "O = ", O

>>> I = Lam u. (u)K = Lam w. (Lam v. (w))O = Lam y. ((y)(y))

Page 22: Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.

Conclusions and future Conclusions and future workwork

Many type systems.Various

implementations. Besides

implementing, our goals include:◦ Proving equivalence of

representations.