1 / 37

Type Classes with

Type Classes with. Functional Dependencies. Mark P Jones, Oregon Graduate Institute. The theory of relational databases. meets. Some values have just one type:. (&&) :: Bool  Bool  Bool. Some values have many types:. length ::  a. List a  Int.

fionn
Download Presentation

Type Classes with

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Type Classes with Functional Dependencies Mark P Jones, Oregon Graduate Institute The theory of relational databases meets

  2. Some values have just one type: (&&) :: Bool  Bool  Bool Some values have many types: length :: a. List a  Int

  3. Some values have several types: (+) :: Int  Int  Int (+) :: Float  Int  Float (+) :: Int  Float  Float (+) :: Float  Float  Float (+) :: …  …  …. Different implementations in each case … Extensible: allows us to add new variants ...

  4. Each type for (+) has the same shape: (+) :: arg1 arg2 res Capture the differences in a table: Add =

  5. Type Classes in Haskell: class Add arg1 arg2 res where (+) :: arg1 arg2 res instance Add Int Int Int where (+) = primIntAdd instance Add Float Float Float where (+) = primFloatAdd instance Add Int Float Float where x+y = (int2Float x) + y …

  6. Int Float Float Float The Hope: (1 + 2.3) + 4.5 Float

  7. Int Float a b The Reality: (1 + 2.3) + 4.5 Float where Add Int Float a Add a Float b

  8. Nothing in the program tells us that we won’t later find an extension of (+): instance Add Int Float Complex where (+) = … Type inference is supposed to infer the most general (principal) type possible. … so the types that we infer have to be general enough to allow for this.

  9. The principal type of (1+2.3)+4.5 is: a.b. (Add Int Float a, Add a Float b)  b A complex type for such a simple example; An inaccurate type — we could be much more precise; An ambiguous type — we can’t give a well-defined semantics for this term.

  10. WANTED! We need a way to: • Persuade type inference to produce better results … • … without compromising extensibility … Solution: let programmers specify type class relations more precisely.

  11. Enter Database Theory: In the theory of (relational) databases: • Data is stored in tables/relations; • Designers specify constraints to capture semantic properties of the data; • Constraints help to ensure consistency and to avoid redundancy.

  12. From “The Theory of Relational Databases”, David Maier, 1983.

  13. DEPARTS is determined by FLIGHT

  14. PILOT is determined by FLIGHT, DATE

  15. {FLIGHT}  {DEPARTS} {FLIGHT, DATE}  {PILOT} The database table corresponds to a relation on attributes {PILOT, FLIGHT, DATE, DEPARTS} that satisfies certain functional dependencies: The theory and practice of functional dependencies are well-developed.

  16. If X and Y are sets of attributes, then: X  Y specifies that, for each tuple: the values of attributes in Y are uniquely determined by the values of the attributes in X. In symbols: for two tuples t, t’: If t|X=t’|X, then t|Y= t’|Y.

  17. Type Classes with Functional Dependencies: Type classes correspond to relations on types … class Add a b c where (+) :: a  b  c

  18. Type Classes with Functional Dependencies: Type classes correspond to relations on types … use functional dependencies to specify them more precisely: class Add a b c | {a,b}  {c}where (+) :: a  b  c

  19. class C a b where … class D a b | {a}  {b} where … class E a b | {a}{b}, {b} {a}where … C is an arbitrary relation on types. D is a partial function on types. E is a partial 1-1 mapping on types.

  20. instance Add Int Int Int where (+) = primIntAdd These are fine! instance Add Float Float Float where (+) = primFloatAdd instance Add Int Float Float where x+y = (int2Float x) + y … The compiler must check that a program’s declaration are consistent with the dependencies:

  21. instance Add Int Float Float where x+y = (int2Float x) + y These are not! instance Add Int Float Complex where (+) = … The compiler must check that a program’s declaration are consistent with the dependencies:

  22. Int Float a The Payback: (1 + 2.3) + 4.5 where Add Int Float a But: Add Int Float Float and so: a = Float

  23. Int Float Float b The Payback: (1 + 2.3) + 4.5 Float where Add Float Float b And so: b = Float

  24. Int Float Float Float The Payback: (1 + 2.3) + 4.5 Float

  25. Type Inference: We infer a type t and a set of constraints P for each term. We can apply “improving substitutions” at any point during type inference … and still get principal types.

  26. Improvement: A substitution Simproves a set of constraints P if it can be applied to P without changing the set of satisfiable instances. For example: [Float/b] improves {Add Float Float b} [a/b] improves {Add a b a, Add a b b}

  27. More generally: Suppose the constraints in P entail C t and C t’, where t, t’ are tuples of types, and C has a dependency X  Y. If t|X=t’|X, then: mgu(t|Y,t’|Y) improves P. mgu(t1,t2) computes most general unifiers.

  28. Other Examples: class Collects e c where empty :: c insert :: e  c  c enum :: c  List e

  29. Other Examples: class Collects e c | {c}  {e}where empty :: c insert :: e  c  c enum :: c  List e

  30. Other Examples: class Collects e c | {c}  {e}where empty :: c insert :: e  c  c enum :: c  List e class FiniteMap i e fm where emptyFM :: fm lookup :: i  fm  Maybe e extend :: i  e  fm  fm

  31. Other Examples: class Collects e c | {c}  {e}where empty :: c insert :: e  c  c enum :: c  List e class FiniteMap i e fm | {fm}{i,e}where emptyFM :: fm lookup :: i  fm  Maybe e extend :: i  e  fm  fm

  32. Other Examples: class Monad m  StateMonad s m where get :: m s set :: s  m ()

  33. Other Examples: class Monad m  StateMonad s m | {m}  {s}where get :: m s set :: s  m () etc …

  34. Related Work: Type Classes (Wadler and Blott, 1989); Parametric Type Classes (Chen, Hudak, Odersky, 1992); Constructor Classes (Jones, 1993); Improvement for Qualified Types (Jones, 1995).

  35. Conclusions: A small extension to the syntax of Haskell; A significant enhancement of multiple parameter type classes in several applications; Implementation distributed in recent versions of Hugs; Opportunities still for further improvement.

  36. Future Work: Functional dependencies can be used to explore the relationship between type classes and implicit parameters (Lewis et al, POPL’00). The interaction of functional dependencies with other aspects (e.g., overlapping instances) of extended Haskell type systems are not yet understood.

  37. Future Work: What other opportunities might there be for exploiting the theory of databases in the design of practical type systems?

More Related