Generating Pieces of Web Applications with Type-Level Programming Adam Chlipala DTP 2010
Verification Types Programmer Effort Strength of Guarantee Ur/Web, Dependent Types Ur/Web, a domain-specific language for metaprogramming Web applications Type-Level Computation Web Applications Programmer Effort Strength of Guarantee
Object-Relational Mapping SQL Table Schema Metaprogram Object-Oriented Interface Add row Modify row Search ...
Automatic Admin Interface SQL Table Schema Id A B C D Metaprogram
In-Browser Spreadsheet
Ad-Hoc Code Generation? Edit some source files to customize.... Now change the database schema.... app models post.rb views posts index.html.erb show.html.erb config routes.rb .... ? SQL Table Schema Id A B C D Metaprogram script/generate scaffold T Id:int A:string B:float C:string D:int
Library uses reflection to behave differently based on object metadata Run-Time Reflection? Library uses reflection to behave differently based on object metadata How do we know that this library is correct? How can we be sure that the library never produces code vulnerable to code injection attacks or other failures of abstraction? SQL Table Schema Id A B C D
A Solution Inspired by Dependent Typing Metaprogram (Static type guarantees correct operation!) Uses type-level computation Code-level iteration over types SQL Table Schema Id A B C D Guaranteed free of injection vulnerabilities, for any metaprogram input
Core Language Features ::= Type | | Name | {} ::= | | ∀ :: . | | :: . | #n | [] | [ = ] | ++ | $ | map | [ ~ ] e ::= x | e e | x : . e | e [] | :: . e | {} | { = e} | e. | e – | e ++ e | [ ~ ] e | e ! Convert “type-level record” to “record type” Apply a function to every field of a record Guarded type: require that two type-level records share no field names Literal field name Empty record Singleton record Record concatenation For type-level record field names For type-level records Empty record Singleton record Field projection Record concatenation Field removal Guarded expression abstraction: require that two type-level records share no field names Guard elimination
The Type-Checker is Clever Algebraic laws are applied automatically: 1 ++ 2 = 2 ++ 1 1 ++ (2 ++ 3) = (1 ++ 2) ++ 3 map (. ) = map f (1 ++ 2) = map f 1 ++ map f 2 map f (map g ) = map (f ○ g)
Ur/Web Available At: http://www.impredicative.com/ur/ Including online demos with syntax-highlighted source code