Transposing F to C Transposing F to C Andrew Kennedy & Don Syme Microsoft Research Cambridge, U.K.

Slides:



Advertisements
Similar presentations
Sml2java a source to source translator Justin Koser, Haakon Larsen, Jeffrey Vaughan PLI 2003 DP-COOL.
Advertisements

Types and Programming Languages Lecture 7 Simon Gay Department of Computing Science University of Glasgow 2006/07.
More ML Compiling Techniques David Walker. Today More data structures lists More functions More modules.
Objects and Classes David Walker CS 320. Advanced Languages advanced programming features –ML data types, exceptions, modules, objects, concurrency,...
Type Systems and Object- Oriented Programming (III) John C. Mitchell Stanford University.
Closures & Environments CS153: Compilers Greg Morrisett.
Type Checking, Inference, & Elaboration CS153: Compilers Greg Morrisett.
CSE341: Programming Languages Lecture 2 Functions, Pairs, Lists Dan Grossman Winter 2013.
Object-Oriented Programming Python. OO Paradigm - Review Three Characteristics of OO Languages –Inheritance It isn’t necessary to build every class from.
Chapter 5: Abstraction, parameterization, and qualification Xinming (Simon) Ou CIS 505: Programming Languages Kansas State University Fall
Control-Flow Graphs & Dataflow Analysis CS153: Compilers Greg Morrisett.
1 Dependent Types for Termination Verification Hongwei Xi University of Cincinnati.
Getting started with ML ML is a functional programming language. ML is statically typed: The types of literals, values, expressions and functions in a.
Object Orientation Chapter SixteenModern Programming Languages, 2nd ed.1 Spring 2012.
Object Orientation Chapter SixteenModern Programming Languages, 2nd ed.1.
ML: a quasi-functional language with strong typing Conventional syntax: - val x = 5; (*user input *) val x = 5: int (*system response*) - fun len lis =
1 Parametric Polymorphism for Popular Programming Languages Andrew Kennedy Microsoft Research Cambridge.
Objects and Classes David Walker CS 320. Advanced Languages advanced programming features –ML data types, exceptions, modules, objects, concurrency,...
Data Abstraction COS 441 Princeton University Fall 2004.
ML: a quasi-functional language with strong typing Conventional syntax: - val x = 5; (*user input *) val x = 5: int (*system response*) - fun len lis =
Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.
Programming Language Semantics Mooly SagivEran Yahav Schrirber 317Open space html://
Modules in UHC A proposal by: Tom Hofte & Eric Eijkelenboom.
CSE 130 : Winter 2006 Programming Languages Ranjit Jhala UC San Diego Lecture 7: Polymorphism.
Feather-Weight Java COS 441 Princeton University Fall 2004.
Semantics with Applications Mooly Sagiv Schrirber html:// Textbooks:Winskel The.
Closure and Environment Compiler Baojian Hua
Subclasses and Subtypes CMPS Subclasses and Subtypes A class is a subclass if it has been built using inheritance. ▫ It says nothing about the meaning.
A Formal Model of Modularity in Aspect-Oriented Programming Jonathan Aldrich : Objects and Aspects Carnegie Mellon University.
1 Abstraction  Identify important aspects and ignore the details  Permeates software development programming languages are abstractions built on hardware.
Self Type Constructors Atsushi Igarashi Kyoto University Joint work with Chieri Saito 1.
Effective C#, Chapter 1: C# Language Elements Last Updated: Fall 2011.
A Theory of Hygienic Macros David Herman, Mitchell Wand Northeastern University.
Evolving the ML Module System Derek Dreyer Toyota Technological Institute at Chicago April 15, 2004.
Genericity Ranga Rodrigo Based on Mark Priestley's Lectures.
Objects & Dynamic Dispatch CSE 413 Autumn Plan We’ve learned a great deal about functional and object-oriented programming Now,  Look at semantics.
Singleton Kinds and Singleton Types Christopher A. Stone August 2, 1999 Thesis Committee Bob Harper, chair Peter Lee John Reynolds Jon Riecke (Bell Laboratories)
Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.
12/9/20151 Programming Languages and Compilers (CS 421) Elsa L Gunter 2112 SC, UIUC Based in part on slides by Mattox.
Just Enough Type Theory or, Featherweight Java A Simple Formal Model of Objects Jonathan Aldrich
Introduction to Object-Oriented Programming Lesson 2.
CMSC 330: Organization of Programming Languages Operational Semantics a.k.a. “WTF is Project 4, Part 3?”
A Type System for Higher-Order Modules Derek Dreyer, Karl Crary, and Robert Harper Carnegie Mellon University POPL 2003.
Advanced Functional Programming Tim Sheard 1 Lecture 17 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science & Technology Lecture:
CMSC 330: Organization of Programming Languages Operational Semantics.
1 Objective Caml (Ocaml) Aaron Bloomfield CS 415 Fall 2005.
Cs776 (Prasad)L2HOF1 Higher-Order Functions. cs776 (Prasad)L2HOF2 Higher-Order Functions A function that takes a function as argument and/or returns a.
Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L05-1 September 21, 2006http:// Types and Simple Type.
Language Paradigms CS655.
1 Interactive Computer Theorem Proving CS294-9 October 19, 2006 Adam Chlipala UC Berkeley Lecture 9: Beyond Primitive Recursion.
Type Checking and Type Inference
Programming Languages and Compilers (CS 421)
Web Design & Development Lecture 9
CSE341: Programming Languages Lecture 17 Implementing Languages Including Closures Dan Grossman Spring 2017.
ML: a quasi-functional language with strong typing
Programming Languages and Compilers (CS 421)
Types of Programming Languages
Programming Language Concepts (CIS 635)
Evolution of programming languages
CSE341: Programming Languages Lecture 17 Implementing Languages Including Closures Dan Grossman Autumn 2018.
Formal Models for Programming Languages
Objects and Aspects: What we’ve seen so far
Agenda SML Docs First-Class Functions Examples Standard Basis
Agenda SML Docs First-Class Functions Examples Standard Basis
CSE341: Programming Languages Lecture 17 Implementing Languages Including Closures Zach Tatlock Winter 2018.
CSE 341 Section 5 Winter 2018.
CSE341: Programming Languages Lecture 17 Implementing Languages Including Closures Dan Grossman Spring 2016.
CSE341: Programming Languages Lecture 17 Implementing Languages Including Closures Dan Grossman Autumn 2017.
CSE341: Programming Languages Lecture 17 Implementing Languages Including Closures Dan Grossman Spring 2019.
Presentation transcript:

Transposing F to C Transposing F to C Andrew Kennedy & Don Syme Microsoft Research Cambridge, U.K.

Transposing what? As musical keys, F and C are far apart As musical keys, F and C are far apart As programming languages, (System) F and (Generic) C are far apart As programming languages, (System) F and (Generic) C are far apart But (message of talk): But (message of talk): Polymorphism in Generic C is as expressive as polymorphism in System F

Polymorphic Programming Languages Standard ML OCaml Eiffel Ada (coming soon…) C (coming soon…) GJ C++ Mercury Clu

Polymorphic features Parameterized datatypes Parameterized classes Polymorphic functions For-all types Polymorphic methods Bounds on type parameters Constraints on type parameters Higher-order polymorphism & kinds Impredicative polymorphism Type classes Variance

System F and C System F and C System F (a.k.a. polymorphic lambda calculus) is very different from C System F (a.k.a. polymorphic lambda calculus) is very different from C System F Generic C Generic C Structural equivalence for types Name equivalence for types No subtyping Subtyping & inheritance First-class functions Virtual methods Quantified types (first-class polymorphism) Parameterized classes & polymorphic methods

System F into C System F into C Despite these differences, we can formalize a translation from System F into (Generic) C that Despite these differences, we can formalize a translation from System F into (Generic) C that is fully type-preserving (no loss of information) is fully type-preserving (no loss of information) is sound (preserves program behaviour) is sound (preserves program behaviour) (second message of talk) demonstrates that… (second message of talk) demonstrates that… polymorphic virtual methods express first-class polymorphism

ML-style polymorphism into C ML-style polymorphism into C Define a datatype: datatype a Tree = Leaf of a | Node of a Tree*a Tree Define a datatype: datatype a Tree = Leaf of a | Node of a Tree*a Tree Write a polymorphic function: fun reflect (t : a Tree) = case t of Leaf a => Leaf a | Node(l,r) => Node(reflect r,reflect l) Write a polymorphic function: fun reflect (t : a Tree) = case t of Leaf a => Leaf a | Node(l,r) => Node(reflect r,reflect l)

Compare: Define parameterized classes: abstract class Tree {... } class Leaf : Tree { A value;... } class Node : Tree { Tree left; Tree right;... } Define parameterized classes: abstract class Tree {... } class Leaf : Tree { A value;... } class Node : Tree { Tree left; Tree right;... } Add a method: abstract class Tree { virtual Tree reflect(); } class Leaf : Tree {... override Tree reflect() { return this; } } class Node : Tree {... override Tree reflect() { return new Node (right.reflect(), left.reflect()); } } Add a method: abstract class Tree { virtual Tree reflect(); } class Leaf : Tree {... override Tree reflect() { return this; } } class Node : Tree {... override Tree reflect() { return new Node (right.reflect(), left.reflect()); } }

In general ML-style datatypes can be translated into parameterized classes ML-style datatypes can be translated into parameterized classes Polymorphic functions can be translated into methods inside a parameterized class e.g. class Mapper { List Map(Function f, List xs) {... } List li =...; List ls = new Mapper ().Map(myFun, li); Polymorphic functions can be translated into methods inside a parameterized class e.g. class Mapper { List Map(Function f, List xs) {... } List li =...; List ls = new Mapper ().Map(myFun, li);

So: Core ML polymorphism can be encoded using parameterized classes alone

Polymorphic virtual methods Define an interface or abstract class: interface Sorter { void Sort (T[] a, IComparer c); } Define an interface or abstract class: interface Sorter { void Sort (T[] a, IComparer c); } Implement the interface: class QuickSort : Sorter {... } class MergeSort : Sorter {... } Implement the interface: class QuickSort : Sorter {... } class MergeSort : Sorter {... } Use instances at many type instantiations: void TestSorter(Sorter s, int[] ia, string[] sa) { s.Sort (ia, IntComparer); s.Sort (sa, StringComparer); } TestSorter(new QuickSort(),...); TestSorter(new MergeSort(),...); Use instances at many type instantiations: void TestSorter(Sorter s, int[] ia, string[] sa) { s.Sort (ia, IntComparer); s.Sort (sa, StringComparer); } TestSorter(new QuickSort(),...); TestSorter(new MergeSort(),...);

Compare: Define an SML signature: signature Sorter = sig val Sort : a array * (a*a->order) –> unit end Define an SML signature: signature Sorter = sig val Sort : a array * (a*a->order) –> unit end Define structures that match the signature: structure QuickSort :> Sorter =... structure MergeSort :> Sorter =... Define structures that match the signature: structure QuickSort :> Sorter =... structure MergeSort :> Sorter =... Use structures at many type instantiations: functor TestSorter(S : Sorter) = struct fun test (ia, sa) = (S.Sort(ia, Int.compare); S.Sort(sa, String.compare) end structure TestQuickSort = TestSorter(QuickSort); TestQuickSort.test(...); structure TestMergeSort = TestSorter(MergeSort); TestMergeSort.test(...); Use structures at many type instantiations: functor TestSorter(S : Sorter) = struct fun test (ia, sa) = (S.Sort(ia, Int.compare); S.Sort(sa, String.compare) end structure TestQuickSort = TestSorter(QuickSort); TestQuickSort.test(...); structure TestMergeSort = TestSorter(MergeSort); TestMergeSort.test(...);

Or (Russo first-class modules): Define an SML signature: signature Sorter = sig val Sort : a array * (a*a->order) –> unit end Define an SML signature: signature Sorter = sig val Sort : a array * (a*a->order) –> unit end Define structures that match the signature: structure QuickSort :> Sorter =... structure MergeSort :> Sorter =... Define structures that match the signature: structure QuickSort :> Sorter =... structure MergeSort :> Sorter =... Use a function to test the structures: fun TestSorter (s, ia, sa) = let structure S as Sorter = s in (S.Sort(ia, Int.compare); S.Sort(sa, String.compare)) end TestSorter ([structure QuickSort as Sorter],...); TestSorter ([structure MergeSort as Sorter],...); Use a function to test the structures: fun TestSorter (s, ia, sa) = let structure S as Sorter = s in (S.Sort(ia, Int.compare); S.Sort(sa, String.compare)) end TestSorter ([structure QuickSort as Sorter],...); TestSorter ([structure MergeSort as Sorter],...);

Question: Can System F first-class polymorphism be encoded using polymorphic virtual methods ?

To answer the question... Take System F + recursion + call-by-value evaluation order Take System F + recursion + call-by-value evaluation order Formalize a type-preserving translation into Generic C# Formalize a type-preserving translation into Generic C# Prove that it works Prove that it works

In more detail Source is System F + CBV recursion: (Types) A,B ::= X | A -> B | forall X.A (Terms) M,N ::= x | M N | rec y(x:A):B.M | M A | ΛX.V (Values) V ::= rec y(x:A):B.M | ΛX.V Source is System F + CBV recursion: (Types) A,B ::= X | A -> B | forall X.A (Terms) M,N ::= x | M N | rec y(x:A):B.M | M A | ΛX.V (Values) V ::= rec y(x:A):B.M | ΛX.V Target is C# minor Target is C# minor a tiny, purely functional subset of Generic C# a tiny, purely functional subset of Generic C# very similar to Featherweight Java (Pierce, Igarashi, Wadler) very similar to Featherweight Java (Pierce, Igarashi, Wadler) includes just enough for our translation plus a bit more (run-time types) includes just enough for our translation plus a bit more (run-time types)

Translation: functions Represent function types using a parameterized class: class Arrow { public virtual Y app(X x); } Represent function types using a parameterized class: class Arrow { public virtual Y app(X x); } Function application is just invocation of app method Function application is just invocation of app method Represent function values by instances of closure classes implementing Arrow e.g. λx:X->Y.x y translates to new C (y) with class C : Arrow,Y> { X y; public override Y app(Arrow x) { return x.app(this.y); } } Represent function values by instances of closure classes implementing Arrow e.g. λx:X->Y.x y translates to new C (y) with class C : Arrow,Y> { X y; public override Y app(Arrow x) { return x.app(this.y); } } Note: Note: fields store free variables of function fields store free variables of function class is parameterized over free type variables of function class is parameterized over free type variables of function

Translation: recursion Translate recursion into self-reference through this Translate recursion into self-reference through this For example, rec y(x:X):X. y(x) translates to new C () with class C : Arrow { public override X app(X x) { return this.app(x); } } For example, rec y(x:X):X. y(x) translates to new C () with class C : Arrow { public override X app(X x) { return this.app(x); } }

Translation: polymorphism We cant use a single class definition for forall types We cant use a single class definition for forall types Instead use different class for each such type e.g. forall X. X->Y is class ForAll_X_XtoY { public virtual Arrow tyapp (); } Instead use different class for each such type e.g. forall X. X->Y is class ForAll_X_XtoY { public virtual Arrow tyapp (); } Type application is just invocation of tyapp method Type application is just invocation of tyapp method Represent polymorphic values by instances of closure classes implementing appropriate ForAll class Represent polymorphic values by instances of closure classes implementing appropriate ForAll class close over free variables and free type variables just as with functions close over free variables and free type variables just as with functions

Translation: polymorphism, cont. Problem: translation of types doesnt commute with substitution i.e. ([A/X]B)* [A*/X]B* Problem: translation of types doesnt commute with substitution i.e. ([A/X]B)* [A*/X]B* Example: Example: forall X.X->Y translates to All_X_XtoY forall X.X->Y translates to All_X_XtoY Now substitute forall Z.Z for Y Now substitute forall Z.Z for Y We get forall X.(X->forall Z.Z) which translates to All_X_XtoAll_Z_Z We get forall X.(X->forall Z.Z) which translates to All_X_XtoAll_Z_Z Solution (Läufer & Odersky): use a single class to represent a whole family of related polymorphic types Solution (Läufer & Odersky): use a single class to represent a whole family of related polymorphic types

Properties of translation Fully type-preserving: A* = B* iff A=B Fully type-preserving: A* = B* iff A=B Translation preserves types of terms: If M:A translates to e then e:A* Translation preserves types of terms: If M:A translates to e then e:A* Translation preserves convergence behaviour of closed terms (i.e. the translation is adequate): If M:A translates to e then M converges iff e converges Translation preserves convergence behaviour of closed terms (i.e. the translation is adequate): If M:A translates to e then M converges iff e converges

Observations Strictly speaking the translation is not compositional (global generation of names for forall types) Strictly speaking the translation is not compositional (global generation of names for forall types) The translation is harnessing the power of polymorphic virtual methods The translation is harnessing the power of polymorphic virtual methods Generic C#, GJ, NextGen permit polymorphic methods to be virtual Generic C#, GJ, NextGen permit polymorphic methods to be virtual Eiffel, C++ do not Eiffel, C++ do not Distinctiveness of polymorphic virtual methods shows up in (type-preserving) implementations Distinctiveness of polymorphic virtual methods shows up in (type-preserving) implementations requires execution-time type application requires execution-time type application

Future work Proof of semantic correctness (adequacy) of translation Proof of semantic correctness (adequacy) of translation use method of logical relations use method of logical relations Harper, Morrisett, Minamide use similar technique to prove correctness of typed closure conversion Harper, Morrisett, Minamide use similar technique to prove correctness of typed closure conversion But: we have impredicative polymorphism and recursion; this makes things tricky But: we have impredicative polymorphism and recursion; this makes things tricky Compositional, partial type-preserving translations Compositional, partial type-preserving translations F ω F ω Dynamic types Dynamic types Power of nominal vs structural equivalence of types Power of nominal vs structural equivalence of types

Questions?