Modular Type ClassesModular Type Classes
Derek Dreyer
Robert Harper
Manuel M.T. Chakravarty
POPL 2007
Nice, France
SpecificationsSpecifications
Haskell:
SpecificationsSpecifications
Haskell:
ML:
ImplementationsImplementations
Haskell:
ImplementationsImplementations
Haskell:
ML:
Generic ImplementationsGeneric Implementations
Haskell:
Generic ImplementationsGeneric Implementations
Haskell:
ML:
Type Classes vs. ModulesType Classes vs. Modules• Haskell type classes (Wadler and Blott, Jones, et al.):
+ Elegant account of ad-hoc polymorphism
– May want different instances of integer equality to be canonical in different scopes
– Not a substitute for a module system
• ML modules (MacQueen, Harper, Leroy, et al.):
+ Explicit, fine-grained control over linking and abstraction
– No support for implicit program construction
Our ProposalOur Proposal• Start with ML modules:
– Classes are just signatures of a special form
– Instances are just structures and functors of a special form
– Allow programmers to designate certain instance modules as canonical within a particular scope
• No tradeoff necessary – Get the best of both worlds!
– Have access to full-featured module system by default
– Can hook into the type inference engine and make use of Haskell-style overloading, if/when you want to
Classes and Instances in MLClasses and Instances in ML
• Great, but now how do we create the eq function?
Creating an Overloaded FunctionCreating an Overloaded Function• We employ an overload mechanism:
• This creates a “polymorphic value” eq, represented internally (in the semantics) as an implicit functor:
• Analogous to Haskell’s qualified types:
Using Using eqeq
• If we apply eq to some arguments of type int * int:
• This initiates a demand for a canonical module of signature
• But none exists ) Type error!
Making an Instance CanonicalMaking an Instance Canonical
• Designate EqInt and EqProd as canonical in a certain scope:
Making an Instance CanonicalMaking an Instance Canonical
• Now if we apply eq in that scope:
• Then the above code typechecks and translates internally to:
• Similar to evidence translation in Haskell:
– Here we use modules as evidence
Class HierarchiesClass Hierarchies
Haskell subclass declaration:
How to support class hierarchies using modules?
Class HierarchiesClass Hierarchies
Haskell subclass declaration:
How to support class hierarchies using modules?
• Use module hierarchies!
Composite Class SignaturesComposite Class Signatures
• Instances of ORD are automatically computed frominstances of EQ and instances of LT
Associated TypesAssociated Types
• Proposed by Chakravarty et al. (2005) as an alternative to“functional dependencies”
– Basic idea: Add type components to classes
• Falls out naturally from modular framework
– Associated types are just type components of class signatures other than the one called t
• In Haskell, requires the introduction of “equality constraints”
– In ML, these are just where type constraints
What Else is in the PaperWhat Else is in the Paper
• Other design points:
– Coercions between implicit and explicit functors
– Coherence in the presence of explicitly-scoped instances
– Handling of overlapping instances
• Type-theoretic formalization (details in the tech report):
– Declarative elaboration semantics (a la Harper-Stone)
– Type inference algorithm
– Algorithm is sound, but not complete(due to problems inherited from both Haskell and ML)
• Related work
Thank You!Thank You!
Extra SlidesExtra Slides
Associated TypesAssociated Types(Chakravarty et al. 05)(Chakravarty et al. 05)
• A function sumColl that sums the elements of a collectionwould have polymorphic type:
Haskell Approach Haskell Approach • Beef up type classes:
– Multi-parameter classes (Jones, Peyton Jones, et al.)– Constructor classes (Jones 95)– Functional dependencies (Jones 00)– Associated types (Chakravarty et al. 05)– …and more
• Each extension brings classes closer to modules,but still no explicit control over linking– Only attempt at explicit control is
“named instances” (Kahl and Scheffczyk 01)
Instance of Ord at IntInstance of Ord at Int
Haskell:
Instance of Ord at IntInstance of Ord at Int
Haskell:
ML:
Instance of Ord at Instance of Ord at ££
Haskell:
Instance of Ord at Instance of Ord at ££
Haskell:
ML:
Instance of Ord at Instance of Ord at ££
Haskell:
ML:
Computing a Composite InstanceComputing a Composite Instance
• Assuming LtInt and LtProd have been “used”, the canonical module of signature
is
Another ExampleAnother Example