Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level...

49
Type Families with Class, Type Classes with Family Alejandro Serrano 1 Jurriaan Hage 1 Patrick Bahr 2 1 Utrecht University 2 IT University of Copenhagen Haskell Symposium 2015

Transcript of Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level...

Page 1: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Type Families with Class,Type Classes with Family

Alejandro Serrano1 Jurriaan Hage1 Patrick Bahr2

1Utrecht University

2IT University of Copenhagen

Haskell Symposium 2015

Page 2: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Motivation

Type-level programming in Haskell/GHC

I functional dependencies

I type families

I data type promotion, kind polymorphism

I closed type families

Goal

I use type families to simulate type classes

I gain flexibility and expressiveness

2 / 18

Page 3: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Motivation

Type-level programming in Haskell/GHC

I functional dependencies

I type families

I data type promotion, kind polymorphism

I closed type families

Goal

I use type families to simulate type classes

I gain flexibility and expressiveness

2 / 18

Page 4: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Overview

I Simulate type classes using type families(without class methods)

I What can we do with this encoding?

I Proposal: type families with elaboration

3 / 18

Page 5: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Encoding type classes

Simplification (for now): type class = predicate on types

class C t1 ... tn IsC :: κ1 → ...→ κn → Bool

Instead of Bool we use:

data Defined = Yes | No

Type family declaration

type family IsC t1 ... tn :: Defined

4 / 18

Page 6: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Encoding type classes

Simplification (for now): type class = predicate on types

class C t1 ... tn IsC :: κ1 → ...→ κn → Bool

Instead of Bool we use:

data Defined = Yes | No

Type family declaration

type family IsC t1 ... tn :: Defined

4 / 18

Page 7: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Encoding type classes

Simplification (for now): type class = predicate on types

class C t1 ... tn IsC :: κ1 → ...→ κn → Bool

Instead of Bool we use:

data Defined = Yes | No

Type family declaration

type family IsC t1 ... tn :: Defined

4 / 18

Page 8: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Encoding type classes

Simplification (for now): type class = predicate on types

class C t1 ... tn IsC :: κ1 → ...→ κn → Defined

Instead of Bool we use:

data Defined = Yes | No

Type family declaration

type family IsC t1 ... tn :: Defined

4 / 18

Page 9: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Encoding type classes

Simplification (for now): type class = predicate on types

class C t1 ... tn IsC :: κ1 → ...→ κn → Defined

Instead of Bool we use:

data Defined = Yes | No

Type family declaration

type family IsC t1 ... tn :: Defined

4 / 18

Page 10: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Example: Eq

Type class declaration

class Eq a where(≡) :: a→ a→ Bool

Translation into type family declaration

type family IsEq (a :: ∗) :: Defined

Usage

type Eq a = IsEq a ∼ Yes

f :: Eq a ⇒ a→ a

5 / 18

Page 11: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Example: Eq

Type class declaration

class Eq a where

(≡) :: a→ a→ Bool

Translation into type family declaration

type family IsEq (a :: ∗) :: Defined

Usage

type Eq a = IsEq a ∼ Yes

f :: Eq a ⇒ a→ a

5 / 18

Page 12: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Example: Eq

Type class declaration

class Eq a where

(≡) :: a→ a→ Bool

Translation into type family declaration

type family IsEq (a :: ∗) :: Defined

Usage

type Eq a = IsEq a ∼ Yes

f :: Eq a ⇒ a→ a

5 / 18

Page 13: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Example: Eq

Type class declaration

class Eq a where

(≡) :: a→ a→ Bool

Translation into type family declaration

type family IsEq (a :: ∗) :: Defined

Usage

type Eq a = IsEq a ∼ Yes

f :: Eq a ⇒ a→ a

5 / 18

Page 14: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Example: Eq

Type class declaration

class Eq a where

(≡) :: a→ a→ Bool

Translation into type family declaration

type family IsEq (a :: ∗) :: Defined

Usage

type Eq a = IsEq a ∼ Yes

f :: IsEq a ∼ Yes ⇒ a→ a

5 / 18

Page 15: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Example: Eq

Type class declaration

class Eq a where

(≡) :: a→ a→ Bool

Translation into type family declaration

type family IsEq (a :: ∗) :: Defined

Usage

type Eq a = IsEq a ∼ Yes

f :: IsEq a ∼ Yes ⇒ a→ a

5 / 18

Page 16: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Example: Eq

Type class declaration

class Eq a where

(≡) :: a→ a→ Bool

Translation into type family declaration

type family IsEq (a :: ∗) :: Defined

Usage

type Eq a = IsEq a ∼ Yes

f :: Eq a ⇒ a→ a

5 / 18

Page 17: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Example: Eq

Type class instance declarations

instance Eq Int where ...

instance Eq a⇒ Eq [a ] where ...

instance (Eq a,Eq b)⇒ Eq (a, b) where ...

Type family instance declarations

type instance IsEq Int = Yes

type instance IsEq [a ] = IsEq a

type instance IsEq (a, b) = And (IsEq a) (IsEq b)

6 / 18

Page 18: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Example: Eq

Type class instance declarations

instance Eq Int where ...

instance Eq a⇒ Eq [a ] where ...

instance (Eq a,Eq b)⇒ Eq (a, b) where ...

Type family instance declarations

type instance IsEq Int = Yes

type instance IsEq [a ] = IsEq a

type instance IsEq (a, b) = And (IsEq a) (IsEq b)

6 / 18

Page 19: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Example: Eq

Type class instance declarations

instance Eq Int where ...

instance Eq a⇒ Eq [a ] where ...

instance (Eq a,Eq b)⇒ Eq (a, b) where ...

Type family instance declarations

type instance IsEq Int = Yes

type instance IsEq [a ] = IsEq a

type instance IsEq (a, b) = And (IsEq a) (IsEq b)

type family And (x :: Defined) (y :: Defined) :: Defined whereAnd Yes Yes = YesAnd x y = No

6 / 18

Page 20: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

What Can We Express

I super classes

I limited forms functional dependencies(requires injective type families)

I not supported: overlapping instances

7 / 18

Page 21: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

What else can we do with this encoding?

I type class directives

I custom error messages

I instance chains

8 / 18

Page 22: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

What else can we do with this encoding?

I type class directives

I custom error messages

I instance chains

8 / 18

Page 23: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Non-membership

type instance IsShow (a→ b) = No

Couldn’t match type ’No with ’Yes

Expected type: ’Yes

Actual type: IsShow (t -> t)

9 / 18

Page 24: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Non-membership

type instance IsShow (a→ b) = No

Couldn’t match type ’No with ’Yes

Expected type: ’Yes

Actual type: IsShow (t -> t)

9 / 18

Page 25: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Closed set of instances

type family IsIntegral t whereIsIntegral Int = YesIsIntegral Integer = YesIsIntegral t = No

10 / 18

Page 26: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Disjointness

data IntegralOrFractional = Integral | Fractional | None

type family IsIntegralOrFractional t :: IntegralOrFractional

type instance IsIntegralOrFractional Int = Integraltype instance IsIntegralOrFractional Integer = Integraltype instance IsIntegralOrFractional Double = Fractional

type IsIntegral t = IsIntegral ′ (IsIntegralOrFractional t)

type family IsIntegral ′ c :: Defined whereIsIntegral ′ Integral = YesIsIntegral ′ c = No

11 / 18

Page 27: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Disjointness

data IntegralOrFractional = Integral | Fractional | None

type family IsIntegralOrFractional t :: IntegralOrFractional

type instance IsIntegralOrFractional Int = Integraltype instance IsIntegralOrFractional Integer = Integraltype instance IsIntegralOrFractional Double = Fractional

type IsIntegral t = IsIntegral ′ (IsIntegralOrFractional t)

type family IsIntegral ′ c :: Defined whereIsIntegral ′ Integral = YesIsIntegral ′ c = No

11 / 18

Page 28: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Disjointness

data IntegralOrFractional = Integral | Fractional | None

type family IsIntegralOrFractional t :: IntegralOrFractional

type instance IsIntegralOrFractional Int = Integraltype instance IsIntegralOrFractional Integer = Integraltype instance IsIntegralOrFractional Double = Fractional

type IsIntegral t = IsIntegral ′ (IsIntegralOrFractional t)

type family IsIntegral ′ c :: Defined whereIsIntegral ′ Integral = YesIsIntegral ′ c = No

11 / 18

Page 29: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Custom Error Messages

data Defined

e

= Yes | No

e

Example

type IsIntegral t = IsIntegral ′ (IsIntegralOrFractional t)

type family IsIntegral ′ c :: Defined Symbol whereIsIntegral ′ Integral = YesIsIntegral ′ Fractional = No "is instance of Factional"

IsIntegral ′ c = No ""

Couldn’t match type ’No "is instance of Fractional"

with ’Yes

Expected type: ’Yes

Actual type: IsIntegral Double

12 / 18

Page 30: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Custom Error Messages

data Defined e = Yes | No e

Example

type IsIntegral t = IsIntegral ′ (IsIntegralOrFractional t)

type family IsIntegral ′ c :: Defined Symbol whereIsIntegral ′ Integral = YesIsIntegral ′ Fractional = No "is instance of Factional"

IsIntegral ′ c = No ""

Couldn’t match type ’No "is instance of Fractional"

with ’Yes

Expected type: ’Yes

Actual type: IsIntegral Double

12 / 18

Page 31: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Custom Error Messages

data Defined e = Yes | No e

Example

type IsIntegral t = IsIntegral ′ (IsIntegralOrFractional t)

type family IsIntegral ′ c :: Defined Symbol whereIsIntegral ′ Integral = YesIsIntegral ′ Fractional = No "is instance of Factional"

IsIntegral ′ c = No ""

Couldn’t match type ’No "is instance of Fractional"

with ’Yes

Expected type: ’Yes

Actual type: IsIntegral Double

12 / 18

Page 32: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Custom Error Messages

data Defined e = Yes | No e

Example

type IsIntegral t = IsIntegral ′ (IsIntegralOrFractional t)

type family IsIntegral ′ c :: Defined Symbol whereIsIntegral ′ Integral = YesIsIntegral ′ Fractional = No "is instance of Factional"

IsIntegral ′ c = No ""

Couldn’t match type ’No "is instance of Fractional"

with ’Yes

Expected type: ’Yes

Actual type: IsIntegral Double12 / 18

Page 33: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Instance Chains [Morris & Jones]

I explicit failure

I provide alternatives (else clause)

Example

instance Show (a→ b) if (Enum a, Show a,Show b) whereshow = ...

else instance Show (a→ b) fails

As type family

type instance IsShow (a→ b) = IsShowFn a btype family IsShowFn a b

= And3 (IsEnum a) (IsShow a) (IsShow b)

13 / 18

Page 34: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Instance Chains [Morris & Jones]

I explicit failure

I provide alternatives (else clause)

Example

instance Show (a→ b) if (Enum a, Show a, Show b) whereshow = ...

else instance Show (a→ b) fails

As type family

type instance IsShow (a→ b) = IsShowFn a btype family IsShowFn a b

= And3 (IsEnum a) (IsShow a) (IsShow b)

13 / 18

Page 35: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Instance Chains [Morris & Jones]

I explicit failure

I provide alternatives (else clause)

Example

instance Show (a→ b) if (Enum a, Show a, Show b) whereshow = ...

else instance Show (a→ b) fails

As type family

type instance IsShow (a→ b) = IsShowFn a btype family IsShowFn a b

= And3 (IsEnum a) (IsShow a) (IsShow b)

13 / 18

Page 36: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

What about class methods?

Two possibilities:

I Use type classes

I Extend type families with elaboration

14 / 18

Page 37: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

What about class methods?

Two possibilities:

I Use type classes

I Extend type families with elaboration

14 / 18

Page 38: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

What about class methods?

Two possibilities:

I Use type classes

I Extend type families with elaboration

data Defined e

p

= Yes

p

| No e

14 / 18

Page 39: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

What about class methods?

Two possibilities:

I Use type classes

I Extend type families with elaboration

data Defined e p = Yes p | No e

14 / 18

Page 40: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

What about class methods?

Two possibilities:

I Use type classes

I Extend type families with elaboration

14 / 18

Page 41: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

What about class methods?

Two possibilities:

I Use type classes

I Extend type families with elaboration

14 / 18

Page 42: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Elaboration at Rewriting

assign a dictionary to type families

Example

type family IsEq (t :: ∗) :: Defineddictionary eq :: t → t → Bool

type instance IsEq Int = Yesdictionary eq = primEqInt -- the primitive Int comparison

type instance IsEq [a ] = e@(IsEq a)dictionary eq [ ] [ ] = True

eq (x : xs) (y : ys) = e@eq x y ∧ eq xs yseq = False

15 / 18

Page 43: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Elaboration at Rewriting

assign a dictionary to type families

Example

type family IsEq (t :: ∗) :: Defineddictionary eq :: t → t → Bool

type instance IsEq Int = Yesdictionary eq = primEqInt -- the primitive Int comparison

type instance IsEq [a ] = e@(IsEq a)dictionary eq [ ] [ ] = True

eq (x : xs) (y : ys) = e@eq x y ∧ eq xs yseq = False

15 / 18

Page 44: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Elaboration at Rewriting

assign a dictionary to type families

Example

type family IsEq (t :: ∗) :: Defineddictionary eq :: t → t → Bool

type instance IsEq Int = Yesdictionary eq = primEqInt -- the primitive Int comparison

type instance IsEq [a ] = e@(IsEq a)dictionary eq [ ] [ ] = True

eq (x : xs) (y : ys) = e@eq x y ∧ eq xs yseq = False

15 / 18

Page 45: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Elaboration at Rewriting

assign a dictionary to type families

Example

type family IsEq (t :: ∗) :: Defineddictionary eq :: t → t → Bool

type instance IsEq Int = Yesdictionary eq = primEqInt -- the primitive Int comparison

type instance IsEq [a ] = e@(IsEq a)dictionary eq [ ] [ ] = True

eq (x : xs) (y : ys) = e@eq x y ∧ eq xs yseq = False

15 / 18

Page 46: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Example: Data Types a la Carte

type family f :<: g :: Defineddictionary inj :: f a→ g awhere e :<: e = Yes dictionary inj = id

f :<: (x :+: y) = d@(Choose f x y l@(f :<: x) r@(f :<: y))dictionary inj = d@choice l@inj r@inj

f :<: g = No

type family Choose f x y fx fy :: Defineddictionary choice :: (f a→ x a)→ (f a→ y a)→ f a→ (x :+: y) awhere Choose f x y Yes fy = Yes

dictionary choice x y = Inl ◦ xChoose f x y fx Yes = Yes

dictionary choice x y = Inr ◦ yChoose f x y fx fy = No

16 / 18

Page 47: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Conclusions

Future work

I study elaboration further

I use encoding as implementation of type classes?

In the paper

I encoding of functional dependencies

I encoding of superclasses

I more examples

I proof of soundness & completeness (using OutsideIn(X))

17 / 18

Page 48: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Conclusions

Future work

I study elaboration further

I use encoding as implementation of type classes?

In the paper

I encoding of functional dependencies

I encoding of superclasses

I more examples

I proof of soundness & completeness (using OutsideIn(X))

17 / 18

Page 49: Type Families with Class, Type Classes with Family · Haskell Symposium 2015. Motivation Type-level programming in Haskell/GHC Ifunctional dependencies Itype families Idata type promotion,

Type Families with Class,Type Classes with Family

Alejandro Serrano1 Jurriaan Hage1 Patrick Bahr2

1Utrecht University

2IT University of Copenhagen

Haskell Symposium 2015