a principled approach to ornamentation in ml
play

A Principled Approach to Ornamentation in ML Thomas Williams , Didier - PowerPoint PPT Presentation

A Principled Approach to Ornamentation in ML Thomas Williams , Didier Rmy Inria - Gallium June 15, 2018 1 Motivation In a statically-typed programming language with ADTs. Imagine we wrote an evaluator for a simple language: type expr = let


  1. A Principled Approach to Ornamentation in ML Thomas Williams , Didier Rémy Inria - Gallium June 15, 2018 1

  2. Motivation In a statically-typed programming language with ADTs. Imagine we wrote an evaluator for a simple language: type expr = let rec eval = function | Const of int | Const i → i | Add of expr × expr | Add ( u , v ) → eval u + eval v | Mul of expr × expr | Mul ( u , v ) → eval u × eval v | ... | ... 2

  3. Motivation In a statically-typed programming language with ADTs. Imagine we wrote an evaluator for a simple language: type expr = let rec eval = function | Const of int | Const i → i | Add of expr × expr | Add ( u , v ) → eval u + eval v | Mul of expr × expr | Mul ( u , v ) → eval u × eval v | ... | ... We change the representation of expressions: type binop ’ = Add ’ | Mul ’ type expr ’ = | Const ’ of int | Binop’ of binop ’ × expr ’ × expr ’ | ... 2

  4. Motivation In a statically-typed programming language with ADTs. Imagine we wrote an evaluator for a simple language: type expr = let rec eval = function | Const of int | Const i → i | Add of expr × expr | Add ( u , v ) → eval u + eval v | Mul of expr × expr | Mul ( u , v ) → eval u × eval v | ... | ... We change the representation of expressions: type binop ’ = Add ’ | Mul ’ type expr ’ = | Const ’ of int | Binop’ of binop ’ × expr ’ × expr ’ | ... What happens to the code we have already written ? 2

  5. Use the types Our first instinct is to compile the code and trust the typechecker: let rec eval : expr → int = function let rec eval ’ : expr ’ → int = function | Const i → i | Const i → i | Add (u, v) → eval u + eval v | Add(u, v) → eval ’ u + eval ’ v | Mul (u, v) → eval u × eval v | Mul(u, v) → eval ’ u × eval ’ v | ... | ... 3

  6. Use the types Our first instinct is to compile the code and trust the typechecker: let rec eval : expr → int = function let rec eval ’ : expr ’ → int = function | Const i → i | Const i → i | Add (u, v) → eval u + eval v | Add(u, v) → eval ’ u + eval ’ v | Mul (u, v) → eval u × eval v | Mul(u, v) → eval ’ u × eval ’ v | ... | ... 3

  7. Use the types Our first instinct is to compile the code and trust the typechecker: let rec eval : expr → int = function let rec eval ’ : expr ’ → int = function | Const i → i | Const’ i → i | Add (u, v) → eval u + eval v | Add(u, v) → eval ’ u + eval ’ v | Mul (u, v) → eval u × eval v | Mul(u, v) → eval ’ u × eval ’ v | ... | ... 3

  8. Use the types Our first instinct is to compile the code and trust the typechecker: let rec eval : expr → int = function let rec eval ’ : expr ’ → int = function | Const i → i | Const’ i → i | Add (u, v) → eval u + eval v | Add(u, v) → eval ’ u + eval ’ v | Mul (u, v) → eval u × eval v | Mul(u, v) → eval ’ u × eval ’ v | ... | ... 3

  9. Use the types Our first instinct is to compile the code and trust the typechecker: let rec eval : expr → int = function let rec eval ’ : expr ’ → int = function | Const i → i | Const’ i → i | Add (u, v) → eval u + eval v | Binop’(Add’,u, v) → eval ’ u + eval ’ v | Mul (u, v) → eval u × eval v | Mul(u, v) → eval ’ u × eval ’ v | ... | ... 3

  10. Use the types Our first instinct is to compile the code and trust the typechecker: let rec eval : expr → int = function let rec eval ’ : expr ’ → int = function | Const i → i | Const’ i → i | Add (u, v) → eval u + eval v | Binop’(Add’,u, v) → eval ’ u + eval ’ v | Mul (u, v) → eval u × eval v | Mul(u, v) → eval ’ u × eval ’ v | ... | ... 3

  11. Use the types Our first instinct is to compile the code and trust the typechecker: let rec eval : expr → int = function let rec eval ’ : expr ’ → int = function | Const i → i | Const’ i → i | Add (u, v) → eval u + eval v | Binop’(Add’,u, v) → eval ’ u + eval ’ v | Mul (u, v) → eval u × eval v | Binop’(Mul’,u, v) → eval ’ u × eval ’ v | ... | ... 3

  12. Use the types Our first instinct is to compile the code and trust the typechecker: let rec eval : expr → int = function let rec eval ’ : expr ’ → int = function | Const i → i | Const’ i → i | Add (u, v) → eval u + eval v | Binop’(Add’,u, v) → eval ’ u + eval ’ v | Mul (u, v) → eval u × eval v | Binop’(Mul’,u, v) → eval ’ u × eval ’ v | ... | ... ◮ Manual process ◮ Long ◮ Error prone ◮ The typechecker misses some places where a change is necessary (exchange fields with the same type) 3

  13. Let’s do better Linking types ◮ In our mental model, the old type and the new type are linked ◮ Let’s keep track of this link ◮ A restricted class of transformation: ornaments, introduced by Conor McBride ◮ A coherence property for lifting functions Related work ◮ Conor McBride, Pierre Dagand ◮ Hsiang-Shang Ko, Jeremy Gibbons ◮ Encoded in Agda ◮ needs dependent types ◮ and powerful encodings What can we do in ML? 4

  14. Ornaments in ML ◮ Define ornamentes as a primitive concept ◮ The correctness of the lifting is not internal anymore ◮ Restrict the transformation (stick to the syntax) to automate the lifting ◮ Prove the correctness of our transformation We built a (prototype) tool for lifting ◮ implements this transformation ◮ on a restricted subset of ML 5

  15. Use the types Instead, define a relation: type expr = type binop ’ = Add ’ | Mul ’ | Const of int type expr ’ = | Add of expr × expr | Const ’ of int | Mul of expr × expr | Binop’ of binop ’ × expr ’ × expr ’ | ... | ... 6

  16. Use ✘✘✘✘✘ the types ornaments ✘ Instead, define a relation: type expr = type binop ’ = Add ’ | Mul ’ | Const of int type expr ’ = | Add of expr × expr | Const ’ of int | Mul of expr × expr | Binop’ of binop ’ × expr ’ × expr ’ | ... | ... type ornament oexpr : expr ⇒ expr ’ with | Const i ⇒ Const ’ i | Add ( u , v ) ⇒ Binop’( Add ’, u ′ , v ′ ) / when ( u , u ′ ) ∈ oexpr | Mul ( u , v ) ⇒ Binop’( Mul ’, u ′ , v ′ ) \ and ( v , v ′ ) ∈ oexpr | ... 6

  17. Use ✘✘✘✘✘ the types ornaments ✘ Instead, define a relation: type expr = type binop ’ = Add ’ | Mul ’ | Const of int type expr ’ = | Add of expr × expr | Const ’ of int | Mul of expr × expr | Binop’ of binop ’ × expr ’ × expr ’ | ... | ... type ornament oexpr : expr ⇒ expr ’ with | Const i ⇒ Const ’ i | Add (u, v) ⇒ Binop’( Add ’, u, v) with u v : oexpr | Mul (u, v) ⇒ Binop’( Mul ’, u, v) with u v : oexpr | ... 6

  18. Use ornaments let rec eval = function | Const i → i | Add ( u , v ) → eval u + eval v | Mul ( u , v ) → eval u × eval v | ... 7

  19. Use ornaments let rec eval = function | Const i → i | Add ( u , v ) → eval u + eval v | Mul ( u , v ) → eval u × eval v | ... let eval ’ = lifting eval : oexpr → int 7

  20. Use ornaments let rec eval = function | Const i → i | Add ( u , v ) → eval u + eval v | Mul ( u , v ) → eval u × eval v | ... let eval ’ = lifting eval : oexpr → int eval u = eval ′ u ′ ( u , u ′ ) ∈ oexpr = ⇒ 7

  21. Use ornaments let rec eval = function let rec eval ’ = function | Const i → i | Const ’ i → i | Add ( u , v ) → eval u + eval v | Binop’( Add ’, u, v) → eval ’ u + eval ’ v | Mul ( u , v ) → eval u × eval v | Binop’( Mul ’, u, v) → eval ’ u × eval ’ v | ... | ... let eval ’ = lifting eval : oexpr → int eval u = eval ′ u ′ ( u , u ′ ) ∈ oexpr = ⇒ 7

  22. Use ornaments let rec eval = function let rec eval ’ = function | Const i → i | Const ’ i → i | Add ( u , v ) → eval u + eval v | Binop’( Add ’, u, v) → eval ’ u + eval ’ v | Mul ( u , v ) → eval u × eval v | Binop’( Mul ’, u, v) → eval ’ u × eval ’ v | ... | ... let eval ’ = lifting eval : oexpr → int eval u = eval ′ u ′ ( u , u ′ ) ∈ oexpr = ⇒ ◮ Clear specification of the function we want ◮ Also gives a specification for our tool ◮ In this case, since the relation is one-to-one, the result is unique 7

  23. Specialization From lists to homogeneous tuples: (not in the version available online) type α list = type α triple = | Nil ( α × α × α ) | Cons of α × α list 8

  24. Specialization From lists to homogeneous tuples: (not in the version available online) type α list = type α triple = | Nil ( α × α × α ) | Cons of α × α list type ornament α list3 : α list → α pair with | Cons (x0, Cons( x1, Cons( x2, Nil ))) ⇒ ( x0, x1, x2 ) | _ ⇒ ∼ 8

  25. Specialization From lists to homogeneous tuples: (not in the version available online) type α list = type α triple = | Nil ( α × α × α ) | Cons of α × α list type ornament α list3 : α list → α pair with | Cons (x0, Cons( x1, Cons( x2, Nil ))) ⇒ ( x0, x1, x2 ) | _ ⇒ ∼ ◮ More than simply reorganizing: restricts the possible values. 8

  26. Specialization let rec map f = function | Nil → Nil | Cons (x, xs) → Cons (f x, xs) 9

  27. Specialization let rec map f = function | Nil → Nil | Cons (x, xs) → Cons (f x, xs) let map_triple = lifting map : ( α → β ) → α list3 → β list3 9

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend