Transcript

Type-level functions for Haskell

Type-level functions for HaskellTom SchrijversK.U.Leuven, Belgiumwith Manuel Chakravarty, Martin Sulzmann and Simon Peyton JonesType-level functionsFunctional programming at the type level!ExamplesUsefulnessInteractionType CheckingEliminating functional dependencies

ExamplesExample: 1 + 1 = 2?-- Peano numeralsdata Zdata Succ n

-- Abbreviationstype One = Succ Ztype Two = Succ One

-- Type-level additiontype family Sum m ntype instance Sum Z n = ntype instance Sum (Succ a) b = Succ (Sum a b)

type function declarationSum :: * -> * -> *1st type function instance2nd type function instanceExample: 1 + 1 = 2?-- Type-level additiontype family Sum m ntype instance Sum Z nat = nattype instance Sum (Succ a) b = Succ (Sum a b)

-- Hypothesishypthesis :: (Sum One One, Two)hypothesis = undefined

-- Testtest :: (a,a) -> Booltest _ = True

Example: 1 + 1 = 2?-- Hypothesishypthesis :: (Sum One One, Two)hypothesis = undefined

-- Testtest :: (a,a) -> Booltest _ = True

-- Proofproof :: Boolproof = test hypothesis

static check: 1+1 = 2Example: Length-indexed Lists-- Length-indexed lists : vectorsdata Vec e l where VNil :: Vec e Z VCons :: e -> Vec e l -> Vec e (Succ l)

-- Safe zip: matched lengthsvzip :: Vec a l -> Vec b l -> Vec (a,b) lvzip VNil VNil = VNilvzip (VCons x xs) (VCons y ys) = VCons (x,y) (vzip xs ys)Example: Length-indexed Lists-- Safe zip: matched lengthsvzip :: Vec a l -> Vec b l -> Vec (a,b) lvzip VNil VNil = VNilvzip (VCons x xs) (VCons y ys) = VCons (x,y) (vzip xs ys)> let l1 = (VCons 1 VNil) l2 = (VCons a (VCons b VNil)) in vzip l1 l212Example: Length-indexed Lists-- Safe zip: matched lengthsvzip :: Vec a l -> Vec b l -> Vec (a,b) lvzip VNil VNil = VNilvzip (VCons x xs) (VCons y ys) = VCons (x,y) (vzip xs ys)> let l1 = (VCons 1 (VCons 2 VNil)) l2 = (VCons a (VCons b VNil)) in vzip l1 l2VCons (1,a) (VCons (2,b) VNil)2=2Example: Length-indexed lists-- concatenationvconc :: Vec a m -> Vec a n -> Vec a ???vconc VNil VNil = VNilVconc (VCons x xs) ys = VCons x (vconc xs ys)Example: Length-indexed lists-- concatenationvconc :: Vec a m -> Vec a n -> Vec a (Sum m n)vconc VNil VNil = VNilVconc (VCons x xs) ys = VCons x (vconc xs ys)> let l1 = (VCons 1) l2 = (VCons a (VCons b VNil)) l3 = vconc l1 l1 in vzip l3 l2VCons (1,a) (VCons (1,b) VNil)1+1=2Example: Collections (1/4)class Collection c where

type Elem c

add :: Elem c -> c -> c list :: c -> [Elem c] elem :: c -> Elem c

Associated type function Elem :: * -> *Associated value functionelem :: c -> Elem cExample: Collections (2/4)instance Collection [e] where type Elem [e] = einstance Collection (Tree e) where type Elem (Tree e) = einstance Collection BitVector where type Elem BitVector = Bittype functions are open!instance Collection [e] where type Elem [e] = e add :: e -> [e] -> [e] add x xs = x : xs

list :: [e] -> [ e ] list xs = xsExample: Collections (3/4)instance Collection [e] where type Elem [e] = e add :: Elem [e] -> [e] -> [e] add x xs = x : xs

list :: [e] -> [Elem [e]] list xs = xsaddAll :: c1 -> c2 -> c2addAll xs ys = foldr add ys (list xs)Example: Collections (4/4)addAll :: Collection c1 => c1 -> c2 -> c2addAll xs ys = foldr add ys (list xs)addAll :: Collection c1, Collection c2 => c1 -> c2 -> c2addAll xs ys = foldr add ys (list xs)addAll :: Collection c1, Collection c2, Elem c1 ~ Elem c2=> c1 -> c2 -> c2addAll xs ys = foldr add ys (list xs)> addAll [0,1,0,1,0] emptyBitVector

context constraint,satisfied by callerElem [Bit] ~ Elem BitVectorSummary of Examplesfunctions over typesopen definitions stand-alone associated to a type classequational constraints in signature contextsusefulnesslimited on their ownreally great withGADTstype classes

Type CheckingCompiler OverviewElem [Int] ~ Int ? Int :: Elem [Int] ~ Int !Compiler Overview(elem [0]) ( Int) == 0elem [0] == 0 : e.Elem [e] = ehypothesisaxiomprooflabelwitnesscastABasic Hindley-Milner[Int] ~ [Int]

syntactic equality (unification)

Type Functions Elem [Int] ~ Int

syntactic equality modulo equational theoryType Checking = Syntactical?Type Checking = Term Rewriting : e.Elem [e] = eAElem [Int] ~ IntIntInt IntIntEquational theory = given equationsToplevel equations: EtContext equations: E gTheorem proving Operational interpretation of theory= Term Rewriting System (Soundness!)

CompletenessTRS must be Strongly Normalizing (SN):Confluent: every type has a canonical formTerminating

Practical & Modular Conditions:Confluence: no overlap of rule headsTerminating:Decreasing recursive callsNo nested calls

Completeness ConditionsPractical & Modular Conditions:Confluence: no overlapElem [e] = eElem [Int] = BitTerminating:Decreasing recursive callsElem [e] = Elem [[e]]No nested callsElem [e] = Elem (F e)F e = [e] Term Rewriting ConditionsEtEgEgWe can do better:Et: satisfy conditionsEg: free form(but no schema variabels)

EtCompletion!Type Checking SummaryEtEgt1 ~ t2Egt ~ t1.Completion2.Rewriting3.Syntactic EqualityIts all been implemented in GHC!Eliminating Functional DependenciesFunctional DependenciesUsing relations as functionsLogic Programming!class Collection c e | c -> e where add :: e -> c -> c list :: c -> [e] elem :: c -> [e]

instance Collection [e] e where ...FDs: Two ProblemsFDs: Solution

FDs: Solution 2Backward Compatibility???Expressiveness lost???FDsTFsautomatic transformationclass FD c ~ e => Collection c e where type FD c add :: e -> c -> c list :: c -> [e] elem :: c -> e

instance Collection [e] e where ...class FD c ~ e => Collection c e where type FD c add :: e -> c -> c list :: c -> [e] elem :: c -> e

instance Collection [e] e where type FD [e] = e class Collection c e | c -> e where add :: e -> c -> c list :: c -> [e] elem :: c -> [e]

instance Collection [e] e where ...class Collection c e | c -> e where type FD c add :: e -> c -> c list :: c -> [e] elem :: c -> e

instance Collection [e] e where ...FDs: Simple TransformationMinimal Impact: class and instance declarations onlyclass FD c ~ e => Collection c where type FD c add :: e -> c -> c list :: c -> [e] elem :: c -> e

instance Collection [e] e where type FD [e] = e class Collection c where type FD c add :: FD c -> c -> c list :: c -> [FD c] elem :: c -> FD c

instance Collection [e] where type FD [e] = e FDs: Advanced TransformationDrop dependent parametersclass FD c ~ e => Collection c e where type FD c add :: e -> c -> c list :: c -> [e] elem :: c -> e

instance Collection [e] e where type FD [e] = e class FD c ~ e => Collection c e where type FD c addAll :: Collection c1 e, Collection c2 e => ...FDs: Advanced TransformationBigger Impact: signature contexts tooclass Collection c where type FD c addAll :: Collection c1 e, Collection c2 e => ...class Collection c where type FD c addAll :: Collection c1, Collection c2, Elem c1 ~ Elem c2 => ...ConclusionConclusionType checking with type functions = Term Rewriting sound, complete and terminatingcompletion algorithm Seemless integration in Haskells rich type systemType classesGADTsUnderstanding functional dependencies betterFuture WorkImprovements and variationsWeaker termination conditionsClosed type functionsRational tree typesEfficiencyApplications: Port librariesRevisit type hacksWrite some papers!Extra SlideRational tree types-- Non-recursive listdata List e t = Nil | Cons e t

-- Fixedpoint operatortype family Fix (k :: *->*)type instance Fix k = k (Fix k)

-- Tie the knottype List e = Fix (List e) = List e (List e (List e ))


Top Related