1 / 22

Implementing a Dependently Typed λ -Calculus

Implementing a Dependently Typed λ -Calculus. Ali Assaf Abbie Desrosiers Alexandre Tomberg. Outline . λ -calculus. Implementation strategies Typed λ -calculus Polymorphic types, System F Dependent types Current work. Motivations. λ -calculus expresses function abstractions

helene
Télécharger la présentation

Implementing a Dependently Typed λ -Calculus

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Implementing a Dependently Typed λ-Calculus Ali Assaf AbbieDesrosiers Alexandre Tomberg

  2. Outline • λ-calculus. • Implementation strategies • Typed λ-calculus • Polymorphic types, System F • Dependent types • Current work

  3. Motivations • λ-calculus expresses function abstractions • Powerful, Turing-complete. • Foundation of functional programming languages. • Strong connection with logic. • This project: • Study types • Explore different implementations

  4. The λ-calculus • Very 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)

  5. Implementation strategies • Explicit substitution • term = var “x” | lam “x” M | app M N • “Natural way” of representing lambda expressions. • Problems : • No immediate α-renaming • Free variable capture problem

  6. Implementation strategies (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.

  7. Implementation strategies (cont’d) • Higher Order Abstract Syntax (HOAS) • Use the features of the meta-language ! • term M = lam f | app M Nwhere f is a function term → term • Term substitution :sub (lam f) N => lam (f N) • α-renaming already provided! • WARNING : Leads to ridiculously short implementations.

  8. Our implementations De Bruijn in SML datatype 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 SML datatype 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)

  9. Our implementations Twelf exp : 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'. SML datatype 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)

  10. The ω problem • Consider 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.

  11. Types • Each 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

  12. Return of the ω • What happens to ω ? • ω = λ x. xxω : α → βx : α, but also x : α → βα ≠ α → β • ω cannot have a valid type! • Simply-typed lambda calculus is strongly normalizing.

  13. Implementing types • Much 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.

  14. Examples • Type 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

  15. Another implementation • Cute 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.

  16. Limitations of simple types • Decidable, but no longer Turing complete. • id = λ x : a . xid = λ 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.

  17. Polymorphism: System F • Idea: 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.

  18. Dependent types : LF • Idea: 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 !

  19. Current work • Polymorphic types in Twelf • Dependent types in Twelf • Types in SML • Problems with HOAS.

  20. Problems with HOAS • Current 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

  21. 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 = ", I print "K = ", K print "O = ", O >>> I = Lam u. (u) K = Lam w. (Lam v. (w)) O = Lam y. ((y)(y))

  22. Conclusions and future work • Many type systems. • Various implementations. • Besides implementing, our goals include: • Proving equivalence of representations.

More Related