Download presentation
Presentation is loading. Please wait.
Published byMaude Campbell Modified over 9 years ago
1
System F with type equality coercions Simon Peyton Jones (Microsoft) Manuel Chakravarty (University of New South Wales) Martin Sulzmann (University of Singapore)
2
Type directed compilation GHC compiles Haskell to a typed intermediate language: System F Two big advantages –Some transformations are guided by types –Type-checking Core is a strong check on correctness of transformations HaskellSystem FC/C--/x86 Optimise GHC “core” language
3
Type directed compilation The Haskell gorilla Dozens of data types; hundreds of contructors System F C/C--/x86 Optimise Two data types Ten constructors
4
System F: the mighty midget System F Polymorphic types, function definitions
5
System F: the mighty midget System F + data types Polymorphic types, function definitions Algebraic data types, pattern matching, list comprehensions,
6
System F: the mighty midget System F + data types Polymorphic types, function definitions Algebraic data types, pattern matching, list comprehensions, Type classes Functional dependencies
7
System F: the mighty midget System F + ( existential ) data types Polymorphic types, function definitions Algebraic data types, pattern matching, list comprehensions, Type classes Functional dependencies Existential data types data T = forall a. MkT a (a → Int) Type of MkT is MkT :: a. a → (a → Int) → T Example of use: case x of MkT v f → f v
8
System F: the fatter midget System F + GADTs Polymorphic types, function definitions Algebraic data types, pattern matching, list comprehensions, Type classes Functional dependencies Existential data types GADTs
9
The problem with F Polymorphic types, function definitions Algebraic data types, pattern matching, list comprehensions, Type classes Functional dependencies Existential data types GADTs Associated types SPLAT
10
A practical problem GHC uses System F + (existential data types) as its intermediate language GADTs are already a Big Thing to add to a typed intermediate language Practical problem: exprType :: Expr -> Type doesn’t have a unique answer any more Associated types are simply a bridge too far What to do?
11
What bits don’t “fit”? The stuff that doesn’t “fit” is the stuff that involves non-syntactic type equality –Functional dependencies –GADTs –Associated types
12
GADTs In the Zero branch, a=Int In the Pair branch, a=(b,c) But how can we express that in System F? data Exp a where Zero :: Exp Int Succ :: Exp Int -> Exp Int Pair :: Exp b -> Exp c -> Exp (b, c) eval :: Exp a -> a eval Zero = 0 eval (Succ e) = eval e + 1 eval (Pair x y) = (eval x, eval y) Also known as “Inductive type families” and “Guarded recursive data types” [Xi POPL’03]
13
Functional dependencies [Jones ESOP’00] Originally designed to guide inference; fundeps cause extra unifications (“improvement”) to take place Absolutely no impact on intermediate language BUT some nasty cases cannot be translated to F class Collects c e | c->e where empty :: c insert :: e -> c -> c instance Eq e => Collects [e] e where... instance Collects BitSet Char where... class Wuggle c where nasty :: (Collects c e) => c -> e -> c instance Wuggle BitSet where...Argh!... nasty :: forall e. Collects BitSet e => c->e->e Can only be Char
14
Associated types [POPL’05, ICFP’05] Elem is a type function, mapping the collection type to the associated element type The original AT papers gave a translation into F by adding type parameters (a la fundep solution) But that is (a) deeply, disgustingly awkward, and (b) suffers from similar nasty cases as fundeps Can we support ATs more directly? class Collects c where type Elem c empty :: c insert :: Elem c -> c -> c instance Eq e => Collects [e] where type Elem [e] = e;... instance Collects BitSet where type Elem BitSet = Char;... foo :: Char -> BitSet foo x = insert x empty
15
The happy answer: FC FC extends System F in a way that...... is much more modest than adding GADTs...supports GADTs...and ATs...and the nasty cases of fundeps...and perhaps other things besides
16
Two ingredients 1.Type-equality coercions : a very well- understood idea in the Types community, but details are interesting. 2.Abstract type constructors and coercion constants : perhaps not so familiar
17
FC in action data Exp a where Zero :: Exp Int Succ :: Exp Int -> Exp Int Pair :: Exp b -> Exp c -> Exp (b, c) eval :: Exp a -> a eval Zero = 0 eval (Succ e) = eval e + 1 eval (Pair x y) = (eval x, eval y) data Exp a where Zero : a.(a Int) => Exp a Succ : a.(a Int) => Exp Int -> Exp a Pair : a. bc.(a (b,c)) => Exp b -> Exp c -> Exp a Result type is always Exp a Type always starts “ a ” Equality constraints express the extra knowledge we can exploit during pattern- matching This part is very standard Some authors use this presentation for the source language (Sheard, Xi, Sulzmann)
18
FC in action data Exp a where Zero :: a.(a Int) => Exp a Succ :: a.(a Int) => Exp Int -> Exp a Pair :: a. bc.(a (b,c)) => Exp b -> Exp c -> Exp a Ordinary value argument Ordinary type argument A coercion argument: “evidence” that Int Int (refl Int) : Int Int We are passing equality evidence around: again, a very standard idea zero : Exp Int zero = Zero Int (refl Int) one : Exp Init one = Succ Int (refl Int) zero
19
FC in action data Exp a where Zero :: a.(a Int) => Exp a Succ :: a.(a Int) => Exp Int -> Exp a Pair :: a. bc.(a (b,c)) => Exp b -> Exp c -> Exp a (sym g) : Int a Pattern matching binds a coercion argument Cast ( ►) exploits the coercion to change the type: 0 : Int (0 ► (sym g)) : a eval:: Exp a -> a eval = a. (x:Exp a). case x of Zero (g:a Int) -> 0 ► (sym g)...
20
Coercions are types! A coercion is a type, not a term. e.g. refl Int : Int Int (refl Int) is a type whose kind is (Int Int) Reasons : 1.Type erasure erases coercions 2.Terms would allow bogus coercions (letrec g = g in g) : Int Bool The type language is strongly normalising; no letrec Weird! A type has a kind, which mentions types...!
21
Abstract type constructors class Collects c where type Elem c empty :: c insert :: Elem c -> c -> c instance Collects BitSet where type Elem BitSet = Char;... instance Eq e => Collects [e] where type Elem [e] = e;... type Elem : * -> * data CollectsD c where CD : c. c -> (Elem c -> c -> c) -> CollectsD c Abstract type constructor: says only “Elem is a type constructor” Class declaration generates a data type declaration as usual
22
Abstract type constructors class Collects c where type Elem c empty :: c insert :: Elem c -> c -> c instance Collects BitSet where type Elem BitSet = Char;... instance Eq e => Collects [e] where type Elem [e] = e;... type Elem :: * -> * data CollectsD c where CD : c. c -> (Elem c -> c -> c) -> CollectsD c Instance decl generates a top-level coercion constant, witnessing that Elem Bitset = Char coercion cBitSet : Elem Bitset Char dBitSet : CollectsD BitSet dBitSet = CD BitSet (...) (...)
23
Abstract type constructors class Collects c where type Elem c empty :: c insert :: Elem c -> c -> c instance Collects BitSet where type Elem BitSet = Char;... instance Eq e => Collects [e] where type Elem [e] = e;... type Elem :: * -> * data CollectsD c where CD : c. c -> (Elem c -> c -> c) -> CollectsD c coercion cBitSet : Elem Bitset Char dBitSet : CollectsD BitSet dBitSet = CD BitSet (...) (...) foo :: Char -> BitSet foo x = insert x empty foo : Char -> BitSet foo x = insertBitSet dBitSet (x ► (sym cBitSet)) (empty BitSet dBitSet)
24
Abstract type constructors class Collects c where type Elem c empty :: c insert :: Elem c -> c -> c instance Collects BitSet where type Elem BitSet = Char;... instance Eq e => Collects [e] where type Elem [e] = e;... type Elem :: * -> * data CollectsD c where CD : c. c -> (Elem c -> c -> c) -> CollectsD c A type-parameterised coercion constant coercion cList : (e:*). Elem [e] e dList : e. CollectsD e -> CollectsD [e] dList =......and a type- and value- parameterised dictionary function
25
A worry What is to stop us saying this? Result: seg-fault city Answer: the top-level coercion constants must be consistent coercion utterlyBogus : Int Bool
26
Some technical details
27
Terms: utterly unremarkable Only interesting feature Used for coercion and application
28
Types Coercions Ordinary types
29
Types Data types Abstract types (must be saturated) Full blown type application
30
Types Coercions are types Various forms of coercions
31
Unsurprising coercions
32
Slightly more surprising If I know (Tree a Tree b) then I know that (a b) Absolutely necessary to translate Haskell programs with GADTs Only true for injective type constructors Not true (in general) for abstract type constructors That’s why applications of abstract type constructors must be saturated
33
Consistency This says that if a coercion relates two data types then they must be identical This condition is both necessary and sufficient for soundness of FC (proof in paper)
34
Operational semantics Largely standard (good) but with some interesting wrinkles A “cvalue” is a plain value possibly wrapped in a cast Coercions are never evaluated at all
35
Standard rules...
36
Not so standard Combine the coercions
37
Not so standard : ( 1 -> 2 ) = ( 1 -> 2 ) 1 : 1 = 1 2 : 2 = 2 Move a coercion on the lambda to a coercion on its argument and result Evaluation carries out proof maintenance Proof terms get bigger and bigger; but can be simplified: sym (sym g) = g sym (refl t) = refl t etc
38
Results: FC itself FC is sound: well-typed FC programs do not go wrong Type erasure does not change the operational behaviour
39
Results: consistency Consistency is a bit like confluence; in general, it’s difficult to prove for a particular program, but whole sub-classes of programs may be consistent by construction If contains no coercion constants then is consistent. This is the GADT case. If a set of coercion constants in form a confluent, terminating rewrite system, then is consistent. This is the AT case.
40
Translating into FC The translation of both GADTs and ATs is almost embarrassingly simple During type inference, any use of equality constraints must be expressed as a coercion in the corresponding FC program
41
Conclusions Feels “right” Next: implement FC in GHC Implications for the source language? Type equalities have the same flavour as sharing constraints in ML modules. Discuss. (e.g. could ML modules be translated into FC?) Paper Apr 2006 (not yet rejected by ICFP’06) http://research.microsoft.com/~simonpj
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.