300 likes | 444 Vues
This paper discusses the integration of modular type classes within Haskell, presenting a novel framework that combines the strengths of Haskell's type classes and ML's modular systems. It addresses issues of ad-hoc polymorphism, instance scoping, and the creation of overloaded functions. The proposed mechanism allows programmers to designate particular instances as canonical, enhancing type inference and providing modularity without sacrificing elegance. With discussions on class hierarchies, associated types, and overall design considerations, this work seeks to bridge the gap between type classes and modules effectively.
E N D
Modular Type Classes Derek Dreyer Robert Harper Manuel M.T. Chakravarty POPL 2007 Nice, France
Specifications Haskell:
Specifications Haskell: ML:
Implementations Haskell:
Implementations Haskell: ML:
Generic Implementations Haskell:
Generic Implementations Haskell: ML:
Type 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 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 canonicalwithin 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 ML • Great, but now how do we create the eq function?
Creating 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 eq • 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 Canonical • Designate EqInt and EqProd as canonical in a certain scope:
Making 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 Hierarchies Haskell subclass declaration: How to support class hierarchies using modules?
Class Hierarchies Haskell subclass declaration: How to support class hierarchies using modules? • Use module hierarchies!
Composite Class Signatures • Instances of ORD are automatically computed frominstances of EQ and instances of LT
Associated 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 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
Associated Types(Chakravarty et al. 05) • A function sumColl that sums the elements of a collectionwould have polymorphic type:
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 Int Haskell:
Instance of Ord at Int Haskell: ML:
Instance of Ord at £ Haskell:
Instance of Ord at £ Haskell: ML:
Instance of Ord at £ Haskell: ML:
Computing a Composite Instance • Assuming LtInt and LtProd have been “used”, the canonical module of signature is