Composing and Decomposing Data Typesuniversity of copenhagendepartment of computer science Faculty...
Transcript of Composing and Decomposing Data Typesuniversity of copenhagendepartment of computer science Faculty...
un i v er s i ty of copenhagen department of computer sc i ence
Faculty of Science
Composing and Decomposing Data TypesA Closed Type Families Implementationof Data Types a la Carte
Patrick BahrUniversity of Copenhagen,Department of Computer [email protected]
10th ACM SIGPLAN Workshop on Generic Programming, 31st August, 2014
Slide 1
un i v er s i ty of copenhagen department of computer sc i ence
Introduction
Experimenting with Closed Type Families
• What can we do with them?
• How do they compare to type classes?
• How do they interact with type classes?
Application: Data Types a la Carte
Specifically: the subtyping constraint :≺:
• Can we get rid of some of the restrictions?
• Can we improve error messages?
• What price do we have to pay?
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 2
un i v er s i ty of copenhagen department of computer sc i ence
Introduction
Experimenting with Closed Type Families
• What can we do with them?
• How do they compare to type classes?
• How do they interact with type classes?
Application: Data Types a la Carte
Specifically: the subtyping constraint :≺:
• Can we get rid of some of the restrictions?
• Can we improve error messages?
• What price do we have to pay?
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 2
un i v er s i ty of copenhagen department of computer sc i ence
Introduction
Experimenting with Closed Type Families
• What can we do with them?
• How do they compare to type classes?
• How do they interact with type classes?
Application: Data Types a la Carte
Specifically: the subtyping constraint :≺:
• Can we get rid of some of the restrictions?
• Can we improve error messages?
• What price do we have to pay?
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 2
un i v er s i ty of copenhagen department of computer sc i ence
Data Types a la Carte [Swierstra 2008]
Idea: Decompose data types into two-level types:
Recursive data type
data Exp = Val Int| Add Exp Exp
=⇒
Fixpoint of functor
data Arith a = Val Int| Add a a
type Exp = Fix Arith
Functors can be combined by coproduct construction :+:
data Mul a = Mul a a
type Exp′ = Fix (Arith :+: Mul)
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 3
un i v er s i ty of copenhagen department of computer sc i ence
Data Types a la Carte [Swierstra 2008]
Idea: Decompose data types into two-level types:
Recursive data type
data Exp = Val Int| Add Exp Exp
=⇒
Fixpoint of functor
data Arith a = Val Int| Add a a
type Exp = Fix Arith
Functors can be combined by coproduct construction :+:
data Mul a = Mul a a
type Exp′ = Fix (Arith :+: Mul)
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 3
un i v er s i ty of copenhagen department of computer sc i ence
Data Types a la Carte [Swierstra 2008]
Idea: Decompose data types into two-level types:
Recursive data type
data Exp = Val Int| Add Exp Exp
=⇒
Fixpoint of functor
data Arith a = Val Int| Add a a
type Exp = Fix Arith
Functors can be combined by coproduct construction :+:
data Mul a = Mul a a
type Exp′ = Fix (Arith :+: Mul)
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 3
un i v er s i ty of copenhagen department of computer sc i ence
Data Types a la Carte [Swierstra 2008]
Idea: Decompose data types into two-level types:
Recursive data type
data Exp = Val Int| Add Exp Exp
=⇒
Fixpoint of functor
data Arith a = Val Int| Add a a
type Exp = Fix Arith
data Fix f = In (f (Fix f ))
Functors can be combined by coproduct construction :+:
data Mul a = Mul a a
type Exp′ = Fix (Arith :+: Mul)
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 3
un i v er s i ty of copenhagen department of computer sc i ence
Data Types a la Carte [Swierstra 2008]
Idea: Decompose data types into two-level types:
Recursive data type
data Exp = Val Int| Add Exp Exp
=⇒
Fixpoint of functor
data Arith a = Val Int| Add a a
type Exp = Fix Arith
Functors can be combined by coproduct construction :+:
data Mul a = Mul a a
type Exp′ = Fix (Arith :+: Mul)
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 3
un i v er s i ty of copenhagen department of computer sc i ence
Data Types a la Carte [Swierstra 2008]
Idea: Decompose data types into two-level types:
Recursive data type
data Exp = Val Int| Add Exp Exp
=⇒
Fixpoint of functor
data Arith a = Val Int| Add a a
type Exp = Fix Arith
Functors can be combined by coproduct construction :+:
data Mul a = Mul a a
type Exp′ = Fix (Arith :+: Mul)
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 3
un i v er s i ty of copenhagen department of computer sc i ence
Data Types a la Carte [Swierstra 2008]
Idea: Decompose data types into two-level types:
Recursive data type
data Exp = Val Int| Add Exp Exp
=⇒
Fixpoint of functor
data Arith a = Val Int| Add a a
type Exp = Fix Arith
Functors can be combined by coproduct construction :+:
data Mul a = Mul a a
type Exp′ = Fix (Arith :+: Mul)
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 3
un i v er s i ty of copenhagen department of computer sc i ence
Data Types a la Carte [Swierstra 2008]
Idea: Decompose data types into two-level types:
Recursive data type
data Exp = Val Int| Add Exp Exp
=⇒
Fixpoint of functor
data Arith a = Val Int| Add a a
type Exp = Fix Arith
Functors can be combined by coproduct construction :+:
data (f :+: g) a = Inl (f a)| Inr (g a)
data Mul a = Mul a a
type Exp′ = Fix (Arith :+: Mul)
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 3
un i v er s i ty of copenhagen department of computer sc i ence
Data Types a la Carte (cont.)
Subtyping constraint :≺:
class f :≺: g whereinj :: f a→ g aprj :: g a→ Maybe (f a)
e.g. Mul :≺: Arith :+: Mul
Example: smart constructors
add :: (Arith :≺: f )⇒ Fix f → Fix f → Fix fadd x y = In (inj (Add x y))
exp :: Fix (Arith :+: Mul)exp = val 1 ‘add ‘ (val 2 ‘mul ‘ val 3)
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 4
un i v er s i ty of copenhagen department of computer sc i ence
Data Types a la Carte (cont.)
Subtyping constraint :≺:
class f :≺: g whereinj :: f a→ g aprj :: g a→ Maybe (f a)
e.g. Mul :≺: Arith :+: Mul
Example: smart constructors
add :: (Arith :≺: f )⇒ Fix f → Fix f → Fix fadd x y = In (inj (Add x y))
exp :: Fix (Arith :+: Mul)exp = val 1 ‘add ‘ (val 2 ‘mul ‘ val 3)
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 4
un i v er s i ty of copenhagen department of computer sc i ence
Data Types a la Carte (cont.)
Subtyping constraint :≺:
class f :≺: g whereinj :: f a→ g aprj :: g a→ Maybe (f a)
e.g. Mul :≺: Arith :+: Mul
Example: smart constructors
add :: (Arith :≺: f )⇒ Fix f → Fix f → Fix fadd x y = In (inj (Add x y))
exp :: Fix (Arith :+: Mul)exp = val 1 ‘add ‘ (val 2 ‘mul ‘ val 3)
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 4
un i v er s i ty of copenhagen department of computer sc i ence
Data Types a la Carte (cont.)
Subtyping constraint :≺:
class f :≺: g whereinj :: f a→ g aprj :: g a→ Maybe (f a)
e.g. Mul :≺: Arith :+: Mul
Example: smart constructors
add :: (Arith :≺: f )⇒ Fix f → Fix f → Fix fadd x y = In (inj (Add x y))
exp :: Fix (Arith :+: Mul)exp = val 1 ‘add ‘ (val 2 ‘mul ‘ val 3)
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 4
un i v er s i ty of copenhagen department of computer sc i ence
Limitations of :≺:
Definition of :≺:
instance f :≺: f where. . .
instance (f :≺: f1)⇒ f :≺: (f1 :+: f2) where. . .
instance (f :≺: f2)⇒ f :≺: (f1 :+: f2) where. . .
• Asymmetric treatment of :+:
• Left-hand side is not inspected
• Ambiguity
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 5
un i v er s i ty of copenhagen department of computer sc i ence
Limitations of :≺:
Definition of :≺:
instance f :≺: f where. . .
instance f :≺: (f :+: f2) where. . .
instance (f :≺: f2)⇒ f :≺: (f1 :+: f2) where. . .
• Asymmetric treatment of :+:
• Left-hand side is not inspected
• Ambiguity
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 5
un i v er s i ty of copenhagen department of computer sc i ence
Limitations of :≺:
Definition of :≺:
instance f :≺: f where. . .
instance f :≺: (f :+: f2) where. . .
instance (f :≺: f2)⇒ f :≺: (f1 :+: f2) where. . .
• Asymmetric treatment of :+:
• Left-hand side is not inspected
• Ambiguity
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 5
un i v er s i ty of copenhagen department of computer sc i ence
Limitations of :≺:
Definition of :≺:
instance f :≺: f where. . .
instance f :≺: (f :+: f2) where. . .
instance (f :≺: f2)⇒ f :≺: (f1 :+: f2) where. . .
• Asymmetric treatment of :+: A :≺: A :+: (B :+: C )
• Left-hand side is not inspected
• Ambiguity
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 5
un i v er s i ty of copenhagen department of computer sc i ence
Limitations of :≺:
Definition of :≺:
instance f :≺: f where. . .
instance f :≺: (f :+: f2) where. . .
instance (f :≺: f2)⇒ f :≺: (f1 :+: f2) where. . .
• Asymmetric treatment of :+: A :6≺: (A :+: B) :+: C
• Left-hand side is not inspected
• Ambiguity
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 5
un i v er s i ty of copenhagen department of computer sc i ence
Limitations of :≺:
Definition of :≺:
instance f :≺: f where. . .
instance f :≺: (f :+: f2) where. . .
instance (f :≺: f2)⇒ f :≺: (f1 :+: f2) where. . .
• Asymmetric treatment of :+: A :6≺: (A :+: B) :+: C
• Left-hand side is not inspected A :+: B :≺: (A :+: B) :+: C
• Ambiguity
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 5
un i v er s i ty of copenhagen department of computer sc i ence
Limitations of :≺:
Definition of :≺:
instance f :≺: f where. . .
instance f :≺: (f :+: f2) where. . .
instance (f :≺: f2)⇒ f :≺: (f1 :+: f2) where. . .
• Asymmetric treatment of :+: A :6≺: (A :+: B) :+: C
• Left-hand side is not inspected A :+: B :6≺: A :+: (B :+: C )
• Ambiguity
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 5
un i v er s i ty of copenhagen department of computer sc i ence
Limitations of :≺:
Definition of :≺:
instance f :≺: f where. . .
instance f :≺: (f :+: f2) where. . .
instance (f :≺: f2)⇒ f :≺: (f1 :+: f2) where. . .
• Asymmetric treatment of :+: A :6≺: (A :+: B) :+: C
• Left-hand side is not inspected A :+: B :6≺: A :+: (B :+: C )
• Ambiguity A :≺: A :+: (A :+: B)
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 5
un i v er s i ty of copenhagen department of computer sc i ence
Contributions
We re-implemented :≺: such that:
• Subtyping behaves as intuitively expected*
• Ambiguous subtyping is avoided
• We can express isomorphism :':
*terms and conditions may applyPatrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 6
un i v er s i ty of copenhagen department of computer sc i ence
Improved subtyping constraint :≺:
Subtyping :≺: behaves as intuitively expected
f :≺: g ⇐⇒ ∃ unique injection from f to g
C :+: A :≺: A :+: B :+: C
Avoid ambiguous subtyping
Multiple occurrences of signatures are rejected:
A :≺: A :+: A :+: C
A :+: A :≺: A :+: B
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 7
un i v er s i ty of copenhagen department of computer sc i ence
Improved subtyping constraint :≺:
Subtyping :≺: behaves as intuitively expected
f :≺: g ⇐⇒ ∃ unique injection from f to g
C :+: A :≺: A :+: B :+: C
Avoid ambiguous subtyping
Multiple occurrences of signatures are rejected:
A :≺: A :+: A :+: C
A :+: A :≺: A :+: B
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 7
un i v er s i ty of copenhagen department of computer sc i ence
Improved subtyping constraint :≺:
Subtyping :≺: behaves as intuitively expected
f :≺: g ⇐⇒ ∃ unique injection from f to g
C :+: A :≺: A :+: B :+: C
Avoid ambiguous subtyping
Multiple occurrences of signatures are rejected:
A :≺: A :+: A :+: C
A :+: A :≺: A :+: B
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 7
un i v er s i ty of copenhagen department of computer sc i ence
Improved subtyping constraint :≺:
Subtyping :≺: behaves as intuitively expected
f :≺: g ⇐⇒ ∃ unique injection from f to g
C :+: A :≺: A :+: B :+: C
Avoid ambiguous subtyping
Multiple occurrences of signatures are rejected:
A :≺: A :+: A :+: C
A :+: A :≺: A :+: B
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 7
un i v er s i ty of copenhagen department of computer sc i ence
Improved subtyping constraint :≺:
Subtyping :≺: behaves as intuitively expected
f :≺: g ⇐⇒ ∃ unique injection from f to g
C :+: A :≺: A :+: B :+: C
Avoid ambiguous subtyping
Multiple occurrences of signatures are rejected:
A :≺: A :+: A :+: C
A :+: A :≺: A :+: B
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 7
un i v er s i ty of copenhagen department of computer sc i ence
Improved subtyping constraint :≺:
Subtyping :≺: behaves as intuitively expected
f :≺: g ⇐⇒ ∃ unique injection from f to g
C :+: A :≺: A :+: B :+: C
Avoid ambiguous subtyping
Multiple occurrences of signatures are rejected:
A :≺: A :+: A :+: C
A :+: A :≺: A :+: B
injection not unique!
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 7
un i v er s i ty of copenhagen department of computer sc i ence
Improved subtyping constraint :≺:
Subtyping :≺: behaves as intuitively expected
f :≺: g ⇐⇒ ∃ unique injection from f to g
C :+: A :≺: A :+: B :+: C
Avoid ambiguous subtyping
Multiple occurrences of signatures are rejected:
A :6≺: A :+: A :+: C
A :+: A :≺: A :+: B
injection not unique!
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 7
un i v er s i ty of copenhagen department of computer sc i ence
Improved subtyping constraint :≺:
Subtyping :≺: behaves as intuitively expected
f :≺: g ⇐⇒ ∃ unique injection from f to g
C :+: A :≺: A :+: B :+: C
Avoid ambiguous subtyping
Multiple occurrences of signatures are rejected:
A :6≺: A :+: A :+: C
A :+: A :≺: A :+: B
injection not unique!
“injection” not injective!
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 7
un i v er s i ty of copenhagen department of computer sc i ence
Improved subtyping constraint :≺:
Subtyping :≺: behaves as intuitively expected
f :≺: g ⇐⇒ ∃ unique injection from f to g
C :+: A :≺: A :+: B :+: C
Avoid ambiguous subtyping
Multiple occurrences of signatures are rejected:
A :6≺: A :+: A :+: C
A :+: A :6≺: A :+: B
injection not unique!
“injection” not injective!
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 7
un i v er s i ty of copenhagen department of computer sc i ence
Type isomorphism constraint :':
We can express isomorphism :':
f :': g ⇐⇒ ∃ unique bijection from f to g
Easy to implement: f :': g = (f :≺: g , g :≺: f )
Use case: improved projection function
The type of the projection function is unsatisfying:
prj :: (f :≺: g)⇒ g a→ Maybe (f a)
With :': we can do better:
split :: (g :': f :+: r)⇒ g a→ Either (f a) (r a)
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 8
un i v er s i ty of copenhagen department of computer sc i ence
Type isomorphism constraint :':
We can express isomorphism :':
f :': g ⇐⇒ ∃ unique bijection from f to g
Easy to implement: f :': g = (f :≺: g , g :≺: f )
Use case: improved projection function
The type of the projection function is unsatisfying:
prj :: (f :≺: g)⇒ g a→ Maybe (f a)
With :': we can do better:
split :: (g :': f :+: r)⇒ g a→ Either (f a) (r a)
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 8
un i v er s i ty of copenhagen department of computer sc i ence
Type isomorphism constraint :':
We can express isomorphism :':
f :': g ⇐⇒ ∃ unique bijection from f to g
Easy to implement: f :': g = (f :≺: g , g :≺: f )
Use case: improved projection function
The type of the projection function is unsatisfying:
prj :: (f :≺: g)⇒ g a→ Maybe (f a)
With :': we can do better:
split :: (g :': f :+: r)⇒ g a→ Either (f a) (r a)
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 8
un i v er s i ty of copenhagen department of computer sc i ence
Type isomorphism constraint :':
We can express isomorphism :':
f :': g ⇐⇒ ∃ unique bijection from f to g
Easy to implement: f :': g = (f :≺: g , g :≺: f )
Use case: improved projection function
The type of the projection function is unsatisfying:
prj :: (f :≺: g)⇒ g a→ Maybe (f a)
With :': we can do better:
split :: (g :': f :+: r)⇒ g a→ Either (f a) (r a)
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 8
un i v er s i ty of copenhagen department of computer sc i ence
Type isomorphism constraint :':
We can express isomorphism :':
f :': g ⇐⇒ ∃ unique bijection from f to g
Easy to implement: f :': g = (f :≺: g , g :≺: f )
Use case: improved projection function
The type of the projection function is unsatisfying:
prj :: (f :≺: g)⇒ g a→ Maybe (f a)
With :': we can do better:
split :: (g :': f :+: r)⇒ g a→ (f a→ b)→ (r a→ b)→ b
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 8
un i v er s i ty of copenhagen department of computer sc i ence
Implementation of :≺:
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 9
un i v er s i ty of copenhagen department of computer sc i ence
Idea
Type-level function Embed :
• take two signatures f , g as arguments
• check whether f :≺: g
• check whether p also proves f :≺: g
Derive implementation of inj and prj :
• also use a type class
• But: use proof object as oracle in instance declarations
No singleton types. This all happens at compile time!
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 10
un i v er s i ty of copenhagen department of computer sc i ence
Idea
Type-level function Embed :
• take two signatures f , g as arguments
• check whether f :≺: g
• check whether p also proves f :≺: g
Derive implementation of inj and prj : ???
• also use a type class
• But: use proof object as oracle in instance declarations
No singleton types. This all happens at compile time!
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 10
un i v er s i ty of copenhagen department of computer sc i ence
Idea
Type-level function Embed :
• take two signatures f , g as arguments
• produce proof object p for f :≺: g
• check whether p also proves f :≺: g
Derive implementation of inj and prj :
• also use a type class
• But: use proof object as oracle in instance declarations
No singleton types. This all happens at compile time!
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 10
un i v er s i ty of copenhagen department of computer sc i ence
Idea
Type-level function Embed :
• take two signatures f , g as arguments
• produce proof object p for f :≺: g
• check whether p also proves f :≺: g
Derive implementation of inj and prj :
• also use a type class
• But: use proof object as oracle in instance declarations
No singleton types. This all happens at compile time!
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 10
un i v er s i ty of copenhagen department of computer sc i ence
Idea
Type-level function Embed :
• take two signatures f , g as arguments
• produce proof object p for f :≺: g
• check whether p also proves f :≺: g
Derive implementation of inj and prj :
• also use a type class
• But: use proof object as oracle in instance declarations
No singleton types. This all happens at compile time!
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 10
un i v er s i ty of copenhagen department of computer sc i ence
Idea
Type-level function Embed :
• take two signatures f , g as arguments
• produce proof object p for f :≺≺: g
• check whether p also proves f :≺: g
Derive implementation of inj and prj :
• also use a type class
• But: use proof object as oracle in instance declarations
No singleton types. This all happens at compile time!
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 10
un i v er s i ty of copenhagen department of computer sc i ence
Idea
Type-level function Embed :
• take two signatures f , g as arguments
• produce proof object p for f :≺≺: g
• check whether p also proves f :≺: g
Derive implementation of inj and prj :
• also use a type class
• But: use proof object as oracle in instance declarations
No singleton types. This all happens at compile time!
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 10
un i v er s i ty of copenhagen department of computer sc i ence
Proof Objects
Definition
data Prf = Refl | Left Prf | Right Prf | Sum Prf Prf
Refl : f :≺≺: f
p : f :≺≺: g1Left p : f :≺≺: g1 :+: g2
p : f :≺≺: g2Right p : f :≺≺: g1 :+: g2
p1 : f1 :≺≺: g p2 : f2 :≺≺: g
Sum p1 p2 : f1 :+: f2 :≺≺: g
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 11
un i v er s i ty of copenhagen department of computer sc i ence
Proof Objects
Definition
data Prf = Refl | Left Prf | Right Prf | Sum Prf Prf
Refl : f :≺≺: f
p : f :≺≺: g1Left p : f :≺≺: g1 :+: g2
p : f :≺≺: g2Right p : f :≺≺: g1 :+: g2
p1 : f1 :≺≺: g p2 : f2 :≺≺: g
Sum p1 p2 : f1 :+: f2 :≺≺: g
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 11
un i v er s i ty of copenhagen department of computer sc i ence
Proof Objects
Definition
data Prf = Refl | Left Prf | Right Prf | Sum Prf Prf
Refl : f :≺≺: f
p : f :≺≺: g1Left p : f :≺≺: g1 :+: g2
p : f :≺≺: g2Right p : f :≺≺: g1 :+: g2
p1 : f1 :≺≺: g p2 : f2 :≺≺: g
Sum p1 p2 : f1 :+: f2 :≺≺: g
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 11
un i v er s i ty of copenhagen department of computer sc i ence
Proof Objects
Definition
data Prf = Refl | Left Prf | Right Prf | Sum Prf Prf
Refl : f :≺≺: f
p : f :≺≺: g1Left p : f :≺≺: g1 :+: g2
p : f :≺≺: g2Right p : f :≺≺: g1 :+: g2
p1 : f1 :≺≺: g p2 : f2 :≺≺: g
Sum p1 p2 : f1 :+: f2 :≺≺: g
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 11
un i v er s i ty of copenhagen department of computer sc i ence
Proof Objects
Definition
data Prf = Refl | Left Prf | Right Prf | Sum Prf Prf
Refl : f :≺≺: f
p : f :≺≺: g1Left p : f :≺≺: g1 :+: g2
p : f :≺≺: g2Right p : f :≺≺: g1 :+: g2
p1 : f1 :≺≺: g p2 : f2 :≺≺: g
Sum p1 p2 : f1 :+: f2 :≺≺: g
kind
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 11
un i v er s i ty of copenhagen department of computer sc i ence
Proof Objects
Definition
data Prf = Refl | Left Prf | Right Prf | Sum Prf Prf
Refl : f :≺≺: f
p : f :≺≺: g1Left p : f :≺≺: g1 :+: g2
p : f :≺≺: g2Right p : f :≺≺: g1 :+: g2
p1 : f1 :≺≺: g p2 : f2 :≺≺: g
Sum p1 p2 : f1 :+: f2 :≺≺: g
kind type
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 11
un i v er s i ty of copenhagen department of computer sc i ence
Proof Objects
Definition
data Prf = Refl | Left Prf | Right Prf | Sum Prf Prf
Refl : f :≺≺: f
p : f :≺≺: g1Left p : f :≺≺: g1 :+: g2
p : f :≺≺: g2Right p : f :≺≺: g1 :+: g2
p1 : f1 :≺≺: g p2 : f2 :≺≺: g
Sum p1 p2 : f1 :+: f2 :≺≺: g
kind type
type constructor
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 11
un i v er s i ty of copenhagen department of computer sc i ence
Construct Proof Objects
data Emb = Found Prf | NotFound | Ambiguous
type family Embed (f :: ∗ → ∗) (g :: ∗ → ∗) :: Emb where
Embed f f = Found ReflEmbed (f1 :+: f2) g = Sum′ (Embed f1 g) (Embed f2 g)Embed f (g1 :+: g2) = Choose (Embed f g1) (Embed f g2)Embed f g = NotFound
type family Choose (e1 :: Emb) (e2 :: Emb) :: Emb whereChoose (Found p1) (Found p2) = AmbiguousChoose Ambiguous e2 = AmbiguousChoose e1 Ambiguous = AmbiguousChoose (Found p1) e2 = Found (Left p1)Choose e1 (Found p2) = Found (Right p2)Choose NotFound NotFound = NotFound
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 12
un i v er s i ty of copenhagen department of computer sc i ence
Construct Proof Objects
data Emb = Found Prf | NotFound | Ambiguous
type family Embed (f :: ∗ → ∗) (g :: ∗ → ∗) :: Emb where
Embed f f = Found ReflEmbed (f1 :+: f2) g = Sum′ (Embed f1 g) (Embed f2 g)Embed f (g1 :+: g2) = Choose (Embed f g1) (Embed f g2)Embed f g = NotFound
type family Choose (e1 :: Emb) (e2 :: Emb) :: Emb whereChoose (Found p1) (Found p2) = AmbiguousChoose Ambiguous e2 = AmbiguousChoose e1 Ambiguous = AmbiguousChoose (Found p1) e2 = Found (Left p1)Choose e1 (Found p2) = Found (Right p2)Choose NotFound NotFound = NotFound
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 12
un i v er s i ty of copenhagen department of computer sc i ence
Construct Proof Objects
data Emb = Found Prf | NotFound | Ambiguous
type family Embed (f :: ∗ → ∗) (g :: ∗ → ∗) :: Emb where
Embed f f = Found ReflEmbed (f1 :+: f2) g = Sum′ (Embed f1 g) (Embed f2 g)Embed f (g1 :+: g2) = Choose (Embed f g1) (Embed f g2)Embed f g = NotFound
type family Choose (e1 :: Emb) (e2 :: Emb) :: Emb whereChoose (Found p1) (Found p2) = AmbiguousChoose Ambiguous e2 = AmbiguousChoose e1 Ambiguous = AmbiguousChoose (Found p1) e2 = Found (Left p1)Choose e1 (Found p2) = Found (Right p2)Choose NotFound NotFound = NotFound
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 12
un i v er s i ty of copenhagen department of computer sc i ence
Construct Proof Objects
data Emb = Found Prf | NotFound | Ambiguous
type family Embed (f :: ∗ → ∗) (g :: ∗ → ∗) :: Emb where
Embed f f = Found ReflEmbed (f1 :+: f2) g = Sum′ (Embed f1 g) (Embed f2 g)Embed f (g1 :+: g2) = Choose (Embed f g1) (Embed f g2)Embed f g = NotFound
type family Choose (e1 :: Emb) (e2 :: Emb) :: Emb whereChoose (Found p1) (Found p2) = AmbiguousChoose Ambiguous e2 = AmbiguousChoose e1 Ambiguous = AmbiguousChoose (Found p1) e2 = Found (Left p1)Choose e1 (Found p2) = Found (Right p2)Choose NotFound NotFound = NotFound
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 12
un i v er s i ty of copenhagen department of computer sc i ence
Post-Processing
This is almost what we want.
• We avoid ambiguity on the right-hand side:
A :6≺: A :+: A :+: C
• We still have ambiguity on the left-hand side:
A :+: A :≺: A :+: B
Solution: check for duplicates in Prf
type family Dupl (p :: Prf ) :: Bool where. . .
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 13
un i v er s i ty of copenhagen department of computer sc i ence
Post-Processing
This is almost what we want.
• We avoid ambiguity on the right-hand side:
A :6≺: A :+: A :+: C
• We still have ambiguity on the left-hand side:
A :+: A :≺: A :+: B
Solution: check for duplicates in Prf
type family Dupl (p :: Prf ) :: Bool where. . .
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 13
un i v er s i ty of copenhagen department of computer sc i ence
Post-Processing
This is almost what we want.
• We avoid ambiguity on the right-hand side:
A :6≺: A :+: A :+: C
• We still have ambiguity on the left-hand side:
A :+: A :≺: A :+: B
Solution: check for duplicates in Prf
type family Dupl (p :: Prf ) :: Bool where. . .
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 13
un i v er s i ty of copenhagen department of computer sc i ence
Post-Processing
This is almost what we want.
• We avoid ambiguity on the right-hand side:
A :6≺: A :+: A :+: C
• We still have ambiguity on the left-hand side:
A :+: A :≺: A :+: B
Solution: check for duplicates in Prf
type family Dupl (p :: Prf ) :: Bool where. . .
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 13
un i v er s i ty of copenhagen department of computer sc i ence
Post-Processing
This is almost what we want.
• We avoid ambiguity on the right-hand side:
A :6≺: A :+: A :+: C
• We still have ambiguity on the left-hand side:
A :+: A :≺: A :+: B
Solution: check for duplicates in Prf
type family Dupl (p :: Prf ) :: Bool where. . .
Sum (Left Refl) (Left Refl)
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 13
un i v er s i ty of copenhagen department of computer sc i ence
Are we there yet?
• Construct proof p for f :≺≺: g
X
• Check whether p proves f :≺: g
X
• Derive inj and prj
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 14
un i v er s i ty of copenhagen department of computer sc i ence
Are we there yet?
• Construct proof p for f :≺≺: g X
• Check whether p proves f :≺: g
X
• Derive inj and prj
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 14
un i v er s i ty of copenhagen department of computer sc i ence
Are we there yet?
• Construct proof p for f :≺≺: g X
• Check whether p proves f :≺: g X
• Derive inj and prj
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 14
un i v er s i ty of copenhagen department of computer sc i ence
Are we there yet?
• Construct proof p for f :≺≺: g X
• Check whether p proves f :≺: g X
• Derive inj and prj
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 14
un i v er s i ty of copenhagen department of computer sc i ence
Derive inj and prj
class f :≺: g whereinj :: f a→ g aprj :: g a→ Maybe (f a)
type f :≺: g = Sub (Embed f g) f g
instance f :≺: f where . . .
instance f :≺: (f :+: g2) where . . .
instance f :≺: g2⇒ f :≺: (g1 :+: g2) where . . .
instance ( f1 :≺: g , f2 :≺: g)⇒ (f1 :+: f2) :≺: g where . . .
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 15
un i v er s i ty of copenhagen department of computer sc i ence
Derive inj and prj
class f :≺: g whereinj :: f a→ g aprj :: g a→ Maybe (f a)
type f :≺: g = Sub (Embed f g) f g
instance f :≺: f where . . .
instance f :≺: g1⇒ f :≺: (g1 :+: g2) where . . .
instance f :≺: g2⇒ f :≺: (g1 :+: g2) where . . .
instance ( f1 :≺: g , f2 :≺: g)⇒ (f1 :+: f2) :≺: g where . . .
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 15
un i v er s i ty of copenhagen department of computer sc i ence
Derive inj and prj
class f :≺: g whereinj :: f a→ g aprj :: g a→ Maybe (f a)
type f :≺: g = Sub (Embed f g) f g
instance f :≺: f where . . .
instance f :≺: g1⇒ f :≺: (g1 :+: g2) where . . .
instance f :≺: g2⇒ f :≺: (g1 :+: g2) where . . .
instance ( f1 :≺: g , f2 :≺: g)⇒ (f1 :+: f2) :≺: g where . . .
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 15
un i v er s i ty of copenhagen department of computer sc i ence
Derive inj and prj
class Sub f g whereinj :: f a→ g aprj :: g a→ Maybe (f a)
type f :≺: g = Sub (Embed f g) f g
instance Sub f f where . . .
instance Sub f g1⇒ Sub f (g1 :+: g2) where . . .
instance Sub f g2⇒ Sub f (g1 :+: g2) where . . .
instance (Sub f1 g ,Sub f2 g)⇒ Sub (f1 :+: f2) g where . . .
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 15
un i v er s i ty of copenhagen department of computer sc i ence
Derive inj and prj
class Sub (e :: Emb) f g whereinj :: f a→ g aprj :: g a→ Maybe (f a)
type f :≺: g = Sub (Embed f g) f g
instance Sub f f where . . .
instance Sub f g1⇒ Sub f (g1 :+: g2) where . . .
instance Sub f g2⇒ Sub f (g1 :+: g2) where . . .
instance (Sub f1 g ,Sub f2 g)⇒ Sub (f1 :+: f2) g where . . .
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 15
un i v er s i ty of copenhagen department of computer sc i ence
Derive inj and prj
class Sub (e :: Emb) f g whereinj :: f a→ g aprj :: g a→ Maybe (f a)
type f :≺: g = Sub (Embed f g) f g
instance Sub (Found Refl) f f where . . .
instance Sub (Found p) f g1⇒ Sub (Found (Left p)) f (g1 :+: g2) where . . .
instance Sub (Found p) f g2⇒ Sub (Found (Right p)) f (g1 :+: g2) where . . .
instance (Sub (Found p1) f1 g ,Sub (Found p2) f2 g)⇒ Sub (Found (Sum p1 p2)) (f1 :+: f2) g where . . .
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 15
un i v er s i ty of copenhagen department of computer sc i ence
Derive inj and prj
class Sub (e :: Emb) f g whereinj :: f a→ g aprj :: g a→ Maybe (f a)
type f :≺: g = Sub (Embed f g) f g
instance Sub (Found Refl) f f where . . .
instance Sub (Found p) f g1⇒ Sub (Found (Left p)) f (g1 :+: g2) where . . .
instance Sub (Found p) f g2⇒ Sub (Found (Right p)) f (g1 :+: g2) where . . .
instance (Sub (Found p1) f1 g ,Sub (Found p2) f2 g)⇒ Sub (Found (Sum p1 p2)) (f1 :+: f2) g where . . .
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 15
un i v er s i ty of copenhagen department of computer sc i ence
Conclusion
• This approach generalises to similar applications
• Improves type class-based implementation in manyaspects
• But:
• We need a way to customise error messages.
• Compile time performance unpredictable.
• Implemented in the compdata package
> cabal install compdata
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 16
un i v er s i ty of copenhagen department of computer sc i ence
Conclusion
• This approach generalises to similar applications
• Improves type class-based implementation in manyaspects
• But:
• We need a way to customise error messages.
• Compile time performance unpredictable.
• Implemented in the compdata package
> cabal install compdata
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 16
un i v er s i ty of copenhagen department of computer sc i ence
Conclusion
• This approach generalises to similar applications
• Improves type class-based implementation in manyaspects
• But:
• We need a way to customise error messages.
• Compile time performance unpredictable.
• Implemented in the compdata package
> cabal install compdata
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 16
un i v er s i ty of copenhagen department of computer sc i ence
Discussion
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 17
un i v er s i ty of copenhagen department of computer sc i ence
Error Messages
• A :≺: B :+: C ?
No instance for
(Sub NotFound A (B :+: C))
• A :+: A :≺: A :+: B ?
No instance for
(Sub Ambiguous (A :+: A) (A :+: B))
• A :≺: A :+: B ?
No instance for
(Sub (Post (Embed a (a :+: B))) a (a :+: B))
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 18
un i v er s i ty of copenhagen department of computer sc i ence
Error Messages
• A :≺: B :+: C ?
No instance for
(Sub NotFound A (B :+: C))
• A :+: A :≺: A :+: B ?
No instance for
(Sub Ambiguous (A :+: A) (A :+: B))
• A :≺: A :+: B ?
No instance for
(Sub (Post (Embed a (a :+: B))) a (a :+: B))
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 18
un i v er s i ty of copenhagen department of computer sc i ence
Error Messages
• A :≺: B :+: C ?
No instance for
(Sub NotFound A (B :+: C))
The original implementation would give:
No instance for (A :<: C)
• A :+: A :≺: A :+: B ?
No instance for
(Sub Ambiguous (A :+: A) (A :+: B))
• A :≺: A :+: B ?
No instance for
(Sub (Post (Embed a (a :+: B))) a (a :+: B))
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 18
un i v er s i ty of copenhagen department of computer sc i ence
Error Messages
• A :≺: B :+: C ?
No instance for
(Sub NotFound A (B :+: C))
• A :+: A :≺: A :+: B ?
No instance for
(Sub Ambiguous (A :+: A) (A :+: B))
• A :≺: A :+: B ?
No instance for
(Sub (Post (Embed a (a :+: B))) a (a :+: B))
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 18
un i v er s i ty of copenhagen department of computer sc i ence
Error Messages
• A :≺: B :+: C ?
No instance for
(Sub NotFound A (B :+: C))
• A :+: A :≺: A :+: B ?
No instance for
(Sub Ambiguous (A :+: A) (A :+: B))
• A :≺: A :+: B ?
No instance for
(Sub (Post (Embed a (a :+: B))) a (a :+: B))
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 18
un i v er s i ty of copenhagen department of computer sc i ence
Error Messages
• A :≺: B :+: C ?
No instance for
(Sub NotFound A (B :+: C))
• A :+: A :≺: A :+: B ?
No instance for
(Sub Ambiguous (A :+: A) (A :+: B))
• a :≺: a :+: B ?
No instance for
(Sub (Post (Embed a (a :+: B))) a (a :+: B))
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 18
un i v er s i ty of copenhagen department of computer sc i ence
Error Messages
• A :≺: B :+: C ?
No instance for
(Sub NotFound A (B :+: C))
• A :+: A :≺: A :+: B ?
No instance for
(Sub Ambiguous (A :+: A) (A :+: B))
• a :≺: a :+: B ?
No instance for
(Sub (Post (Embed a (a :+: B))) a (a :+: B))
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 18
un i v er s i ty of copenhagen department of computer sc i ence
Compile Time Performance
• If done “wrong”, this implementation can be very slow!
• Implementation presented here: O(n2)
• Slightly different implementation: O(2n)(but essentially the same)
• micro benchmark:• derive F :≺: G• 9 summands in F and G• Implementation presented here: 0.5s• Naive implementation: 45s
• Type families on kind ∗ are expensive!
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 19
un i v er s i ty of copenhagen department of computer sc i ence
Compile Time Performance
• If done “wrong”, this implementation can be very slow!
• Implementation presented here: O(n2)
• Slightly different implementation: O(2n)(but essentially the same)
• micro benchmark:• derive F :≺: G• 9 summands in F and G• Implementation presented here: 0.5s• Naive implementation: 45s
• Type families on kind ∗ are expensive!
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 19
un i v er s i ty of copenhagen department of computer sc i ence
Compile Time Performance
• If done “wrong”, this implementation can be very slow!
• Implementation presented here: O(n2)
• Slightly different implementation: O(2n)(but essentially the same)
• micro benchmark:• derive F :≺: G• 9 summands in F and G• Implementation presented here: 0.5s• Naive implementation: 45s
• Type families on kind ∗ are expensive!
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 19
un i v er s i ty of copenhagen department of computer sc i ence
Compile Time Performance
• If done “wrong”, this implementation can be very slow!
• Implementation presented here: O(n2)
• Slightly different implementation: O(2n)(but essentially the same)
• micro benchmark:• derive F :≺: G• 9 summands in F and G
• Implementation presented here: 0.5s• Naive implementation: 45s
• Type families on kind ∗ are expensive!
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 19
un i v er s i ty of copenhagen department of computer sc i ence
Compile Time Performance
• If done “wrong”, this implementation can be very slow!
• Implementation presented here: O(n2)
• Slightly different implementation: O(2n)(but essentially the same)
• micro benchmark:• derive F :≺: G• 9 summands in F and G• Implementation presented here: 0.5s
• Naive implementation: 45s
• Type families on kind ∗ are expensive!
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 19
un i v er s i ty of copenhagen department of computer sc i ence
Compile Time Performance
• If done “wrong”, this implementation can be very slow!
• Implementation presented here: O(n2)
• Slightly different implementation: O(2n)(but essentially the same)
• micro benchmark:• derive F :≺: G• 9 summands in F and G• Implementation presented here: 0.5s• Naive implementation: 45s
• Type families on kind ∗ are expensive!
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 19
un i v er s i ty of copenhagen department of computer sc i ence
Compile Time Performance
• If done “wrong”, this implementation can be very slow!
• Implementation presented here: O(n2)
• Slightly different implementation: O(2n)(but essentially the same)
• micro benchmark:• derive F :≺: G• 9 summands in F and G• Implementation presented here: 0.5s• Naive implementation: 45s
• Type families on kind ∗ are expensive!
Patrick Bahr — Composing and Decomposing Data Types — WGP ’14, 31st August, 2014
Slide 19