Title: Transposing F to C?
1Transposing F to C?
- Andrew Kennedy Don SymeMicrosoft Research
Cambridge, U.K.
2Transposing what?
- As musical keys, F and C? are far apart
- As programming languages, (System) F and
(Generic) C? are far apart - But (message of talk)
Polymorphism in Generic C? is as expressive as
polymorphism in System F
3Polymorphic Programming Languages
Standard ML
Eiffel
OCaml
C
Ada
C? (coming soon)
Mercury
Clu
GJ
4Polymorphic features
Impredicative polymorphism
Parameterized classes
Parameterized datatypes
For-all types
Polymorphic functions
Higher-order polymorphism kinds
Polymorphic methods
Type classes
Bounds on type parameters
Constraints on type parameters
Variance
5System F and C?
- System F (a.k.a. polymorphic lambda calculus) is
very different from C?
6System F into C?
- Despite these differences, we can formalize a
translation from System F into (Generic) C? that - is fully type-preserving (no loss of information)
- is sound (preserves program behaviour)
- (second message of talk) demonstrates that
polymorphic virtual methodsexpressfirst-class
polymorphism
7ML-style polymorphism into C?
- Define a datatype datatype a Tree Leaf of
a Node of a Treea Tree - Write a polymorphic functionfun reflect (t
a Tree) case t of Leaf a gt Leaf a
Node(l,r) gt Node(reflect r,reflect l)
8Compare
- Define parameterized classes abstract class
TreeltAgt ... class LeafltAgt TreeltAgt A
value ... class NodeltAgt TreeltAgt TreeltAgt
left TreeltAgt right ... - Add a methodabstract class TreeltAgt virtual
TreeltAgt reflect() class LeafltAgt TreeltAgt
... override TreeltAgt reflect() return
this class NodeltAgt TreeltAgt ...
override TreeltAgt reflect() return new
NodeltAgt(right.reflect(), left.reflect())
9In general
- ML-style datatypes can be translated into
parameterized classes - Polymorphic functions can be translated into
methods inside a parameterized class e.g.class
MapperltA,Bgt ListltBgt Map(FunctionltA,Bgt f,
ListltAgt xs) ... Listltintgt li
...Listltstringgt ls new Mapperltint,stringgt().Ma
p(myFun, li)
10So
Core ML polymorphism can be encodedusing
parameterized classes alone
11Polymorphic virtual methods
- Define an interface or abstract classinterface
Sorter void SortltTgt(T a, IComparerltTgt c) - Implement the interfaceclass QuickSort
Sorter ... class MergeSort Sorter ... - Use instances at many type instantiationsvoid
TestSorter(Sorter s, int ia, string sa)
s.Sortltintgt(ia, IntComparer)
s.Sortltstringgt(sa, StringComparer)TestSorter(
new QuickSort(), ...)TestSorter(new
MergeSort(), ...)
12Compare
- Define an SML signaturesignature Sorter sig
val Sort a array (aa-gtorder) gt unit
end - Define structures that match the
signaturestructure QuickSort gt Sorter ...
structure MergeSort gt Sorter ... - Use structures at many type instantiationsfunct
or TestSorter(S Sorter) struct fun test
(ia, sa) (S.Sort(ia, Int.compare)
S.Sort(sa, String.compare) endstructure
TestQuickSort TestSorter(QuickSort)
TestQuickSort.test(...)structure TestMergeSort
TestSorter(MergeSort) TestMergeSort.test(...)
13Or (Russo first-class modules)
- Define an SML signaturesignature Sorter sig
val Sort a array (aa-gtorder) gt unit
end - Define structures that match the
signaturestructure QuickSort gt Sorter ...
structure MergeSort gt Sorter ... - Use a function to test the structuresfun
TestSorter (s, ia, sa) let structure S as
Sorter s in (S.Sort(ia, Int.compare)
S.Sort(sa, String.compare)) endTestSorter
(structure QuickSort as Sorter,
...)TestSorter (structure MergeSort as
Sorter, ...)
14Question
- Can System F first-class polymorphism be
encoded using polymorphic virtual methods - ?
15To answer the question...
- Take System F recursion call-by-value
evaluation order - Formalize a type-preserving translation into
Generic C - Prove that it works
16In more detail
- Source is System F CBV recursion(Types) A,B
X A -gt B forall X.A(Terms) M,N x M
N rec y(xA)B.M M A ?X.V(Values) V
rec y(xA)B.M ?X.V - Target is C minor
- a tiny, purely functional subset of Generic C
- very similar to Featherweight Java (Pierce,
Igarashi, Wadler) - includes just enough for our translation plus a
bit more (run-time types)
17Translation functions
- Represent function types using a parameterized
classclass ArrowltX,Ygt public virtual Y
app(X x) - Function application is just invocation of app
method - Represent function values by instances of
closure classes implementing Arrow e.g.
?xX-gtY.x y translates to new CltX,Ygt(y)
withclass CltX,Ygt ArrowltArrowltX,Ygt,Ygt X y
public override Y app(ArrowltX,Ygt x)
return x.app(this.y) - Note
- fields store free variables of function
- class is parameterized over free type variables
of function
18Translation recursion
- Translate recursion into self-reference through
this - For example, rec y(xX)X. y(x) translates to new
CltXgt() withclass CltXgt ArrowltX,Xgt public
override X app(X x) return this.app(x)
19Translation polymorphism
- We cant use a single class definition for
forall types - Instead use different class for each such
typee.g. forall X. X-gtY isclass
ForAll_X_XtoYltYgt public virtual ArrowltX,Ygt
tyappltXgt() - Type application is just invocation of tyapp
method - Represent polymorphic values by instances of
closure classes implementing appropriate ForAll
class - close over free variables and free type variables
just as with functions
20Translation polymorphism, cont.
- Problem translation of types doesnt commute
with substitution i.e.(A/XB) ? A/XB - Example
- forall X.X-gtY translates to All_X_XtoYltYgt
- Now substitute forall Z.Z for Y
- We get forall X.(X-gtforall 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
21Properties of translation
- Fully type-preserving A B iff AB
- Translation preserves types of terms If MA
translates to e then eA - Translation preserves convergence behaviour of
closed terms (i.e. the translation is
adequate) If MA translates to e then M
converges iff e converges
22Observations
- Strictly speaking the translation is not
compositional (global generation of names for
forall types) - The translation is harnessing the power of
polymorphic virtual methods - Generic C, GJ, NextGen permit polymorphic
methods to be virtual - Eiffel, C do not
- Distinctiveness of polymorphic virtual methods
shows up in (type-preserving) implementations - requires execution-time type application
23Future work
- Proof of semantic correctness (adequacy) of
translation - use method of logical relations
- Harper, Morrisett, Minamide use similar technique
to prove correctness of typed closure conversion - But we have impredicative polymorphism and
recursion this makes things tricky - Compositional, partial type-preserving
translations - F?
- Dynamic types
- Power of nominal vs structural equivalence of
types
24Questions?