1 / 38

Type-level functions for Haskell

Type-level functions for Haskell. Tom Schrijvers K.U.Leuven , Belgium. with Manuel Chakravarty , Martin Sulzmann and Simon Peyton Jones. Type-level functions. Functional programming at the type level!. Examples Usefulness Interaction Type Checking

gittel
Download Presentation

Type-level functions for Haskell

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-level functions for Haskell Tom Schrijvers K.U.Leuven, Belgium with Manuel Chakravarty, Martin Sulzmann and Simon Peyton Jones

  2. Type-level functions Functional programming at the type level! • Examples • Usefulness • Interaction • Type Checking • Eliminating functional dependencies

  3. Examples

  4. Example: 1 + 1 = 2? -- Peano numerals dataZ dataSuccn -- Abbreviations typeOne = Succ Z typeTwo = Succ One -- Type-level addition typefamilySummn typeinstanceSumZn = n typeinstanceSum (Succa) b = Succ (Suma b) type function declaration Sum :: * -> * -> * 1st type function instance 2nd type function instance

  5. Example: 1 + 1 = 2? -- Type-level addition typefamilySummn typeinstanceSumZnat = nat typeinstanceSum (Succa) b = Succ (Suma b) -- Hypothesis hypthesis :: (Sum One One, Two) hypothesis = undefined -- Test test :: (a,a) -> Bool test _ = True

  6. Example: 1 + 1 = 2? -- Hypothesis hypthesis :: (Sum One One, Two) hypothesis = undefined -- Test test :: (a,a) -> Bool test _ = True -- Proof proof :: Bool proof = test hypothesis static check: 1+1 = 2

  7. Example: Length-indexed Lists -- Length-indexed lists : vectors dataVec e lwhere VNil :: Vec e Z VCons :: e -> Vec e l -> Vec e (Succ l) -- Safe zip: matched lengths vzip :: Vec a l -> Vec b l -> Vec (a,b) l vzipVNilVNil = VNil vzip (VCons x xs) (VCons y ys) = VCons (x,y) (vzipxsys)

  8. Example: Length-indexed Lists -- Safe zip: matched lengths vzip :: Vec a l -> Vec b l -> Vec (a,b) l vzipVNilVNil = VNil vzip (VCons x xs) (VCons y ys) = VCons (x,y) (vzipxsys) 1≠2 > let l1 = (VCons 1 VNil) l2 = (VCons ‘a’ (VCons ‘b’ VNil)) in vzip l1 l2

  9. Example: Length-indexed Lists -- Safe zip: matched lengths vzip :: Vec a l -> Vec b l -> Vec (a,b) l vzipVNilVNil = VNil vzip (VCons x xs) (VCons y ys) = VCons (x,y) (vzipxsys) 2=2 > let l1’ = (VCons 1 (VCons 2 VNil)) l2 = (VCons ‘a’ (VCons ‘b’ VNil)) in vzip l1’ l2 VCons (1,’a’) (VCons (2,’b’) VNil)

  10. Example: Length-indexed lists -- concatenation vconc :: Vec a m -> Vec a n -> Vec a ??? vconcVNilVNil= VNil Vconc (VCons x xs) ys = VCons x (vconcxsys)

  11. Example: Length-indexed lists -- concatenation vconc :: Vec a m -> Vec a n -> Vec a (Sum m n) vconcVNilVNil= VNil Vconc (VCons x xs) ys = VCons x (vconcxsys) 1+1=2 > let l1 = (VCons 1) l2 = (VCons ‘a’ (VCons ‘b’ VNil)) l3 = vconc l1 l1 in vzip l3 l2 VCons (1,’a’) (VCons (1,’b’) VNil)

  12. Example: Collections (1/4) classCollection c where typeElem c add :: Elem c -> c -> c list :: c -> [Elem c] elem :: c -> Elem c Associated value function elem :: c -> Elem c Associated type function Elem :: * -> *

  13. Example: Collections (2/4) instanceCollection [e] where typeElem [e] = e type functions are open! instanceCollection (Tree e) where typeElem (Tree e) = e instanceCollection BitVectorwhere typeElemBitVector = Bit

  14. Example: Collections (3/4) instanceCollection [e] where typeElem [e] = e add :: e -> [e] -> [e] add x xs = x : xs list :: [e] -> [ e ] list xs = xs instanceCollection [e] where typeElem [e] = e add :: Elem [e] -> [e] -> [e] add x xs = x : xs list :: [e] -> [Elem [e]] list xs = xs

  15. Example: Collections (4/4) context constraint, satisfied by caller addAll :: c1 -> c2 -> c2 addAllxsys = foldr add ys (list xs) addAll :: Collection c1 => c1 -> c2 -> c2 addAllxsys = foldr add ys (list xs) addAll :: Collection c1, Collection c2 => c1 -> c2 -> c2 addAllxsys = foldr add ys (list xs) addAll :: Collection c1, Collection c2, Elem c1 ~ Elem c2=> c1 -> c2 -> c2 addAllxsys = foldr add ys (list xs) Elem [Bit] ~ Elem BitVector > addAll [0,1,0,1,0] emptyBitVector <010101>

  16. Summary of Examples • functions over types • open definitions • stand-alone • associated to a type class • equational constraints in signature contexts • usefulness • limited on their own • really great with • GADTs • type classes

  17. Type Checking

  18. Compiler Overview

  19. Compiler Overview label elem [0] == 0 γ : e.Elem [e] = e A axiom Elem [Int] ~ Int ? hypothesis γInt :: Elem [Int] ~ Int ! proof cast witness (elem [0]) ► (γInt) == 0

  20. Type Checking = Syntactical? • Basic Hindley-Milner [Int] ~ [Int] syntactic equality (unification) • Type Functions Elem [Int] ~ Int syntactic equality modulo equational theory

  21. Type Checking = Term Rewriting • Equational theory = given equations • Toplevel equations: Et • Context equations: E g • Theorem proving • Operational interpretation of theory • = Term Rewriting System (Soundness!) γ : e.Elem [e] = e A Elem [Int] ~ Int γInt Int Int ≡ Int

  22. Completeness TRS must be Strongly Normalizing (SN): • Confluent: every type has a canonical form • Terminating • Practical & Modular Conditions: • Confluence: • no overlap of rule heads • Terminating: • Decreasing recursive calls • No nested calls

  23. Completeness Conditions • Practical & Modular Conditions: • Confluence: no overlap • Elem [e] = e • Elem [Int] = Bit • Terminating: • Decreasingrecursivecalls • Elem [e] = Elem [[e]] • Nonested calls • Elem [e] = Elem (F e) • F e = [e]

  24. Term Rewriting Conditions • We can do better: • Et: satisfy conditions • Eg: free form (but no schema variabels) √ Et Et √  Eg Eg’ Completion!

  25. Type Checking Summary Et It’s all been implemented in GHC! Eg Eg’ 3.Syntactic Equality 1.Completion t ~ t t1 ~ t2 2.Rewriting

  26. Eliminating Functional Dependencies

  27. Functional Dependencies • Using relations as functions • Logic Programming! classCollection c e | c -> e where add :: e -> c -> c list :: c -> [e] elem :: c -> [e] instanceCollection [e] e where ...

  28. FDs: Two Problems

  29. FDs: Solution

  30. FDs: Solution 2 • Backward Compatibility??? • Expressiveness lost??? FDs TFs automatic transformation

  31. FDs: Simple Transformation Minimal Impact: class and instance declarations only classFD c ~ e => Collection c ewhere type FDc add :: e -> c -> c list :: c -> [e] elem :: c -> e instanceCollection [e] e where ... classFD c ~ e => Collection c ewhere type FDc add :: e -> c -> c list :: c -> [e] elem :: c -> e instanceCollection [e] e where type FD[e] = e classCollection c e | c -> e where add :: e -> c -> c list :: c -> [e] elem :: c -> [e] instanceCollection [e] e where ... classCollection c e | c -> e where type FDc add :: e -> c -> c list :: c -> [e] elem :: c -> e instanceCollection [e] e where ...

  32. FDs: Advanced Transformation Drop dependent parameters classFD c ~ e => Collection c where type FDc add :: e -> c -> c list :: c -> [e] elem :: c -> e instanceCollection [e] e where type FD[e] = e classCollectionc where type FDc add :: FD c-> c -> c list :: c -> [FD c] elem :: c -> FD c instanceCollection [e] where type FD[e] = e classFD c ~ e => Collection c ewhere type FDc add :: e -> c -> c list :: c -> [e] elem :: c -> e instanceCollection [e] e where type FD[e] = e

  33. FDs: Advanced Transformation Bigger Impact: signature contexts too classFD c ~ e => Collectionc ewhere type FDc addAll :: Collection c1 e, Collection c2 e => ... classCollectionc where type FDc addAll :: Collection c1 e, Collection c2 e => ... classCollectionc where type FDc addAll :: Collection c1, Collection c2, Elem c1 ~ Elem c2 => ...

  34. Conclusion

  35. Conclusion • Type checking with type functions = Term Rewriting • sound, complete and terminating • completion algorithm • Seemless integration in Haskell’s rich type system • Type classes • GADTs • Understanding functional dependencies better

  36. Future Work • Improvements and variations • Weaker termination conditions • Closed type functions • Rational tree types • Efficiency • Applications: • Port libraries • Revisit type hacks • Write some papers!

  37. Extra Slide

  38. Rational tree types -- Non-recursive list data List’ e t = Nil | Cons e t -- Fixedpoint operator typefamilyFix (k :: *->*) typeinstanceFix k = k (Fix k) -- Tie the knot type List e = Fix (List’ e) = List’ e (List’ e (List’ e …))

More Related