Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Evolving Existing Languages: The Typed Racket Experience

Evolving Existing Languages: The Typed Racket Experience

A talk given in November 2010 at Indiana University

Sam Tobin-Hochstadt

September 26, 2011
Tweet

More Decks by Sam Tobin-Hochstadt

Other Decks in Programming

Transcript

  1. Evolving Existing Languages The Typed Racket Experience Sam Tobin-Hochstadt PLT

    @ Northeastern University Nov 29, 2010 Indiana University
  2. Typed Racket Smooth Interoperation - Typed/Untyped Interaction Easy Migration -

    Types for Existing Programs Comprehensive Reuse - Building on Existing Languages
  3. Functions ack #lang racket ; ack : Integer Integer ->

    Integer (define (ack m n) (cond [(<= m 0) (+ n 1)] [(<= n 0) (ack (- m 1) 1)] [else (ack (- m 1) (ack m (- n 1)))])) (ack 2 3)
  4. Functions ack #lang typed/racket (: ack : Integer Integer ->

    Integer) (define (ack m n) (cond [(<= m 0) (+ n 1)] [(<= n 0) (ack (- m 1) 1)] [else (ack (- m 1) (ack m (- n 1)))])) (ack 2 3)
  5. Modules ack #lang racket ; ack : Integer Integer ->

    Integer (define (ack m n) (cond [(<= m 0) (+ n 1)] [(<= n 0) (ack (- m 1) 1)] [else (ack (- m 1) (ack m (- n 1)))])) compute #lang racket (require ack) (ack 2 3)
  6. Modules ack #lang typed/racket (: ack : Integer Integer ->

    Integer) (define (ack m n) (cond [(<= m 0) (+ n 1)] [(<= n 0) (ack (- m 1) 1)] [else (ack (- m 1) (ack m (- n 1)))])) compute #lang racket (require ack) (ack 2 3)
  7. Modules ack #lang racket ; ack : Integer Integer ->

    Integer (define (ack m n) (cond [(<= m 0) (+ n 1)] [(<= n 0) (ack (- m 1) 1)] [else (ack (- m 1) (ack m (- n 1)))])) compute #lang typed/racket (require [ack (Integer Integer -> Integer)]) (ack 2 3)
  8. Modules ack #lang typed/racket (: ack : Integer Integer ->

    Integer) (define (ack m n) (cond [(<= m 0) (+ n 1)] [(<= n 0) (ack (- m 1) 1)] [else (ack (- m 1) (ack m (- n 1)))])) compute #lang typed/racket (require ack) (ack 2 3)
  9. Typed & Untyped server #lang typed/racket (: add5 (Number ->

    Number)) (define (add5 x) (+ x 5)) client #lang racket (require server) (add5 7)
  10. Typed & Untyped Untyped code can make mistakes server #lang

    typed/racket (: add5 (Number -> Number)) (define (add5 x) (+ x 5)) client #lang racket (require server) (add5 "seven")
  11. Typed & Untyped Untyped code can make mistakes server #lang

    typed/racket (: add5 (Number -> Number)) (define (add5 x) ) client #lang racket (require server) (add5 "seven") +: expects type <number> as 1st argument
  12. Typed & Untyped Catch errors dynamically at the boundary server

    #lang typed/racket (: add5 (Number -> Number)) (define (add5 x) (+ x 5)) client #lang racket (require server) (add5 "seven") client broke the contract on add5
  13. Typed & Untyped Catch errors dynamically at the boundary server

    #lang racket (define (add5 x) "x plus 5") client #lang typed/racket (require server [add5 (Number -> Number)]) (add5 7) server interface broke the contract on add5
  14. Typed & Untyped Catch errors dynamically at the boundary server

    #lang typed/racket (: addx (Number -> (Number -> Number))) (define (addx x) (lambda (y) (+ x y))) client #lang racket (require server) ((addx 7) 'bad) client broke the contract on add5
  15. The Blame Theorem If the program raises a contract error,

    the blame is not assigned to a typed module.
  16. The Blame Theorem Allows local reasoning about typed modules, without

    changing untyped modules. Choose how much static checking you want.
  17. Types for Existing Programs occur #lang typed/racket (define-type Peano (U

    'Z (List 'S Peano))) (: convert : Peano -> Number) (define (convert n) (cond [(symbol? n) 0] [else (add1 (convert (rest n)))]))
  18. Types for Existing Programs refine #lang typed/racket (: check :

    String -> (Refinement sql-safe?)) (define (check s) (if (sql-safe? s) s (error "unsafe string!")))
  19. Types for Existing Programs union #lang typed/racket (define-type BT (U

    Number (Pair BT BT))) (: sizeof : BT -> Number) (define (sizeof b) (if (number? b) 1 (+ 1 (sizeof (car b)) (sizeof (cdr b)))))
  20. Types for Existing Programs varar #lang typed/racket (: wrap (∀

    (B A ...) (A ... -> B) -> (A ... -> B))) (define (wrap f) (λ args (printf "args are: ~a\n" args) (apply f args)))
  21. Occurrence Typing (define-type Peano (U 'Z (List 'S Peano))) (:

    convert : Peano -> Number) (define (convert n) (cond [(symbol? n) 0] [else (add1 (convert (rest n)))]))
  22. Occurrence Typing (define-type Peano (U 'Z (List 'S Peano))) (:

    convert : Peano -> Number) (define (convert n) (cond [(symbol? n) 0] [else (add1 (convert (rest n)))])) n : Peano n n : Peano
  23. Occurrence Typing (define-type Peano (U 'Z (List 'S Peano))) (:

    convert : Peano -> Number) (define (convert n) (cond [(symbol? n) 0] [else (add1 (convert (rest n)))])) n : Peano n n : Peano
  24. Occurrence Typing (define-type Peano (U 'Z (List 'S Peano))) (:

    convert : Peano -> Number) (define (convert n) (cond [(symbol? n) 0] [else (add1 (convert (rest n)))])) n : 'Z 0 n : 'Z
  25. Occurrence Typing (define-type Peano (U 'Z (List 'S Peano))) (:

    convert : Peano -> Number) (define (convert n) (cond [(symbol? n) 0] [else (add1 (convert (rest n)))])) n : (List 'S Peano) n n : (List 'S Peano)
  26. Occurrence Typing (: combine : (U String Symbol) (U String

    Symbol) -> String) (define (combine s s*) (cond [(and (string? s) (string? s*)) (string-append s s*)] [(string? s) (string-append s (symbol->string s*))] [(string? s*) (string-append (symbol->string s) s*)] [else (string-append (symbol->string s) (symbol->string s*))]))
  27. Occurrence Typing (: combine : (U String Symbol) (U String

    Symbol) -> String) (define (combine s s*) (cond [(and (string? s) (string? s*)) (string-append s s*)] [(string? s) (string-append s (symbol->string s*))] [(string? s*) (string-append (symbol->string s) s*)] [else (string-append (symbol->string s) (symbol->string s*))])) s : (U String Symbol) s* : (U String Symbol) s s : (U String Symbol) s* s* : (U String Symbol)
  28. Occurrence Typing (: combine : (U String Symbol) (U String

    Symbol) -> String) (define (combine s s*) (cond [(and (string? s) (string? s*)) (string-append s s*)] [(string? s) (string-append s (symbol->string s*))] [(string? s*) (string-append (symbol->string s) s*)] [else (string-append (symbol->string s) (symbol->string s*))])) s : String s* : String s s : String s* s* : String
  29. Occurrence Typing (: combine : (U String Symbol) (U String

    Symbol) -> String) (define (combine s s*) (cond [(and (string? s) (string? s*)) (string-append s s*)] [(string? s) (string-append s (symbol->string s*))] [(string? s*) (string-append (symbol->string s) s*)] [else (string-append (symbol->string s) (symbol->string s*))])) s : String s* : Symbol s s : String s* s* : Symbol
  30. Occurrence Typing (: combine : (U String Symbol) (U String

    Symbol) -> String) (define (combine s s*) (cond [(and (string? s) (string? s*)) (string-append s s*)] [(string? s) (string-append s (symbol->string s*))] [(string? s*) (string-append (symbol->string s) s*)] [else (string-append (symbol->string s) (symbol->string s*))])) s : Symbol s* : String s s : Symbol s* s* : String
  31. Occurrence Typing (: combine : (U String Symbol) (U String

    Symbol) -> String) (define (combine s s*) (cond [(and (string? s) (string? s*)) (string-append s s*)] [(string? s) (string-append s (symbol->string s*))] [(string? s*) (string-append (symbol->string s) s*)] [else (string-append (symbol->string s) (symbol->string s*))])) s : Symbol s* : Symbol s s : Symbol s* s* : Symbol
  32. Occurrence Typing (define-type Peano (U 'Z (List 'S Peano))) (:

    convert : Peano -> Number) (define (convert n) (cond [(symbol? n) 0] [else (add1 (convert (rest n)))]))
  33. Occurrence Typing (define-type Peano (U 'Z (List 'S Peano))) (:

    convert : Peano -> Number) (define (convert n) (cond [(symbol? n) 0] [else (add1 (convert (rest n)))])) n : (List 'S Peano) (add1 (convert (rest n))) n : (List 'S Peano)
  34. Occurrence Typing (define-type Peano (U 'Z (List 'S Peano))) (:

    convert : Peano -> Number) (define (convert n) (cond [(symbol? n) 0] [else (add1 (convert (rest n)))])) ⊢ (List 'S Peano) @ n (add1 (convert (rest n))) ⊢ (List 'S Peano) @ n
  35. Occurrence Typing (define-type Peano (U 'Z (List 'S Peano))) (:

    convert : Peano -> Number) (define (convert n) (cond [(symbol? n) 0] [else (add1 (convert (rest n)))])) ⊢ (List 'S Peano) @ n (symbol? n) ⊢ Symbol @ n
  36. Occurrence Typing (define-type Peano (U 'Z (List 'S Peano))) (:

    convert : Peano -> Number) (define (convert n) (cond [(symbol? n) 0] [else (add1 (convert (rest n)))])) ⊢ Peano @ n ⊢ Symbol @ n ⊢ (List 'S Peano) @ n (symbol? n) ⊢ Symbol @ n
  37. Occurrence Typing (define-type Peano (U 'Z (List 'S Peano))) (:

    convert : Peano -> Number) (define (convert n) (cond [(symbol? n) 0] [else (add1 (convert (rest n)))])) ⊢ (U 'Z (List 'S Peano)) @ n ⊢ Symbol @ n ⊢ (List 'S Peano) @ n (symbol? n) ⊢ Symbol @ n
  38. Occurrence Typing (: combine : (U String Symbol) (U String

    Symbol) -> String) (define (combine s s*) (cond [(and (string? s) (string? s*)) (string-append s s*)] [(string? s) (string-append s (symbol->string s*))] [(string? s*) (string-append (symbol->string s) s*)] [else (string-append (symbol->string s) (symbol->string s*))]))
  39. Occurrence Typing (: combine : (U String Symbol) (U String

    Symbol) -> String) (define (combine s s*) (cond [(and (string? s) (string? s*)) (string-append s s*)] [(string? s) (string-append s (symbol->string s*))] [(string? s*) (string-append (symbol->string s) s*)] [else (string-append (symbol->string s) (symbol->string s*))])) ⊢ String @ s ⊢ String @ s* (string-append s s*) ⊢ String @ s ⊢ String @ s*
  40. Occurrence Typing (: combine : (U String Symbol) (U String

    Symbol) -> String) (define (combine s s*) (cond [(and (string? s) (string? s*)) (string-append s s*)] [(string? s) (string-append s (symbol->string s*))] [(string? s*) (string-append (symbol->string s) s*)] [else (string-append (symbol->string s) (symbol->string s*))])) ⊢ String @ s ∧ String @ s* ⊢ String @ s ⊢ String @ s* (string? s) String @ s (string? s*) String @ s*
  41. Occurrence Typing (: combine : (U String Symbol) (U String

    Symbol) -> String) (define (combine s s*) (cond [(and (string? s) (string? s*)) (string-append s s*)] [(string? s) (string-append s (symbol->string s*))] [(string? s*) (string-append (symbol->string s) s*)] [else (string-append (symbol->string s) (symbol->string s*))])) ⊢ Symbol @ s* (string-append s (symbol->string s*)) Symbol @ s*
  42. Occurrence Typing (: combine : (U String Symbol) (U String

    Symbol) -> String) (define (combine s s*) (cond [(and (string? s) (string? s*)) (string-append s s*)] [(string? s) (string-append s (symbol->string s*))] [(string? s*) (string-append (symbol->string s) s*)] [else (string-append (symbol->string s) (symbol->string s*))])) ⊢ String @ s ⊢ String @ s ⊃ String @ s* ⊢ Symbol @ s* (and (string? s) (string? s*)) String @ s ⊃ String @ s* (string? s) String @ s
  43. Languages as Libraries typed/racket #lang racket (define-syntax (#%module-begin stx) ....)

    (module name typed/racket (#%module-begin ....) ) #%module-begin #%module-begin
  44. Defining A Language (define-syntax (#%module-begin stx) (syntax-parse stx [(_ forms

    ...) (let () (for ([f (syntax->list #'(forms ...))]) (typecheck f)) #'(#%plain-module-begin forms ...))]))
  45. Defining A Language (define-syntax (#%module-begin stx) (syntax-parse stx [(_ forms

    ...) (let () (for ([f (syntax->list #'(forms ...))]) (typecheck f)) #'(#%plain-module-begin forms ...))])) f
  46. Defining A Language (define-syntax (#%module-begin stx) (syntax-parse stx [(_ forms

    ...) (let ([forms* (local-expand #'(forms ...))]) (for ([f (rest (syntax->list forms*))]) (typecheck f)) #'(#%plain-module-begin #,forms*))]))
  47. Defining A Language (define-syntax (#%module-begin stx) (syntax-parse stx [(_ forms

    ...) (let ([forms* (local-expand #'(forms ...))]) (for ([f (rest (syntax->list forms*))]) (typecheck f)) (let ([forms** (optimize forms*)]) #'(#%plain-module-begin #,forms**)))]))
  48. Typechecking (define (typecheck f) (syntax-parse f ; variables [v:identifier (lookup-type

    #'v)] ; abstractions [(lambda (x) e) (define t (syntax-property #'x 'type-label)) (set-type! #'x t) (typecheck #'e)] ; about 10 more cases ....))
  49. Typechecking (define (typecheck f) (syntax-parse f ; variables [v:identifier (lookup-type

    #'v)] ; abstractions [(lambda (x) e) (define t (syntax-property #'x 'type-label)) (set-type! #'x t) (typecheck #'e)] ; about 10 more cases ....))
  50. Typechecking (define (typecheck f) (syntax-parse f ; variables [v:identifier (lookup-type

    #'v)] ; abstractions [(lambda (x) e) (define t (syntax-property #'x 'type-label)) (set-type! #'x t) (typecheck #'e)] ; about 10 more cases ....))
  51. Optimization #lang typed/racket (: norm : Float Float -> Float)

    (define (norm x y) (flsqrt (+ (* x x) (* y y))))
  52. Optimization #lang typed/racket (: norm : Float Float -> Float)

    (define (norm x y) (unsafe-flsqrt (unsafe-fl+ (unsafe-fl* x x) (unsafe-fl* y y))))
  53. Contracts (Vectorof (Integer -> Integer)) (class/c ....) (unit/c ....) Analysis

    using contracts With Stevie Strickland, Robby Findler, Matthew Flatt, David Van Horn
  54. Types First-class Classes Generic Operations Variable-Arity Functions .... and Inference

    With Stevie Strickland, Asumu Takikawa, Matthias Felleisen
  55. Education Beginner-Level Error Messages #lang typed/racket (first 3) Type Checker:

    Polymorphic function first could not be applied to arguments: Domains: (Pairof a (Listof b)) (Listof a) Arguments: Positive-Fixnum With Eli Barzilay, Matthias Felleisen
  56. Jesse Tov Felix Klock Eli Barzilay Ivan Gazeau Thanks! Available

    from racket-lang.org Supported by the Mozilla Foundation
  57. Jesse Tov Felix Klock Eli Barzilay Ivan Gazeau Neil Toronto

    Thanks! Available from racket-lang.org Supported by the Mozilla Foundation
  58. Jesse Tov Felix Klock Eli Barzilay Ivan Gazeau Neil Toronto

    Aaron Turon Thanks! Available from racket-lang.org Supported by the Mozilla Foundation
  59. Jesse Tov Felix Klock Eli Barzilay Ivan Gazeau Neil Toronto

    Aaron Turon Carl Eastlund Thanks! Available from racket-lang.org Supported by the Mozilla Foundation
  60. Jesse Tov Felix Klock Eli Barzilay Ivan Gazeau Neil Toronto

    Aaron Turon Carl Eastlund Robby Findler Thanks! Available from racket-lang.org Supported by the Mozilla Foundation
  61. Jesse Tov Felix Klock Eli Barzilay Ivan Gazeau Neil Toronto

    Aaron Turon Carl Eastlund Robby Findler Jay McCarthy Thanks! Available from racket-lang.org Supported by the Mozilla Foundation
  62. Jesse Tov Felix Klock Eli Barzilay Ivan Gazeau Neil Toronto

    Aaron Turon Carl Eastlund Robby Findler Jay McCarthy Matthew Flatt Thanks! Available from racket-lang.org Supported by the Mozilla Foundation
  63. Jesse Tov Felix Klock Eli Barzilay Ivan Gazeau Neil Toronto

    Aaron Turon Carl Eastlund Robby Findler Jay McCarthy Matthew Flatt Hari Prashanth Thanks! Available from racket-lang.org Supported by the Mozilla Foundation
  64. Jesse Tov Felix Klock Eli Barzilay Ivan Gazeau Neil Toronto

    Aaron Turon Carl Eastlund Robby Findler Jay McCarthy Matthew Flatt Hari Prashanth Ryan Culpepper Thanks! Available from racket-lang.org Supported by the Mozilla Foundation
  65. Jesse Tov Felix Klock Eli Barzilay Ivan Gazeau Neil Toronto

    Aaron Turon Carl Eastlund Robby Findler Jay McCarthy Matthew Flatt Hari Prashanth Ryan Culpepper David Van Horn Thanks! Available from racket-lang.org Supported by the Mozilla Foundation
  66. Jesse Tov Felix Klock Eli Barzilay Ivan Gazeau Neil Toronto

    Aaron Turon Carl Eastlund Robby Findler Jay McCarthy Matthew Flatt Hari Prashanth Ryan Culpepper David Van Horn Stevie Strickland Thanks! Available from racket-lang.org Supported by the Mozilla Foundation
  67. Jesse Tov Felix Klock Eli Barzilay Ivan Gazeau Neil Toronto

    Aaron Turon Carl Eastlund Robby Findler Jay McCarthy Matthew Flatt Hari Prashanth Ryan Culpepper David Van Horn Stevie Strickland Matthias Felleisen Thanks! Available from racket-lang.org Supported by the Mozilla Foundation
  68. Jesse Tov Felix Klock Eli Barzilay Ivan Gazeau Neil Toronto

    Aaron Turon Carl Eastlund Robby Findler Jay McCarthy Matthew Flatt Hari Prashanth Ryan Culpepper David Van Horn Stevie Strickland Matthias Felleisen Vincent St-Amour Thanks! Available from racket-lang.org Supported by the Mozilla Foundation
  69. Jesse Tov Felix Klock Eli Barzilay Ivan Gazeau Neil Toronto

    Aaron Turon Carl Eastlund Robby Findler Jay McCarthy Matthew Flatt Hari Prashanth Ryan Culpepper David Van Horn Stevie Strickland Matthias Felleisen Vincent St-Amour Shriram Krishnamurthi Thanks! Available from racket-lang.org Supported by the Mozilla Foundation
  70. Jesse Tov Felix Klock Eli Barzilay Ivan Gazeau Neil Toronto

    Aaron Turon Carl Eastlund Robby Findler Jay McCarthy Matthew Flatt Hari Prashanth Ryan Culpepper David Van Horn Stevie Strickland Matthias Felleisen Vincent St-Amour Shriram Krishnamurthi Students at Northeastern and Brown Thanks! Available from racket-lang.org Supported by the Mozilla Foundation
  71. Jesse Tov Felix Klock Eli Barzilay Ivan Gazeau Neil Toronto

    Aaron Turon Carl Eastlund Robby Findler Jay McCarthy Matthew Flatt Hari Prashanth Ryan Culpepper David Van Horn Stevie Strickland Matthias Felleisen Vincent St-Amour Shriram Krishnamurthi Students at Northeastern and Brown And everyone who has tried Typed Racket! Thanks! Available from racket-lang.org Supported by the Mozilla Foundation
  72. Jesse Tov Felix Klock Eli Barzilay Ivan Gazeau Neil Toronto

    Aaron Turon Carl Eastlund Robby Findler Jay McCarthy Matthew Flatt Hari Prashanth Ryan Culpepper David Van Horn Stevie Strickland Matthias Felleisen Vincent St-Amour Shriram Krishnamurthi Students at Northeastern and Brown And everyone who has tried Typed Racket! Thanks! Available from racket-lang.org Supported by the Mozilla Foundation