Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kind signatures and Type families

Tags:

types

haskell

I expect

type family Rep a

and

type family Rep :: * -> *

to be the same, but it seems there is a difference

type family   Rep a
type instance Rep Int  = Char
-- ok

type family   Rep :: * -> *
type instance Rep Int  = Char
-- Expected kind * -> *, but got 'Int' instead

Have I simply stumbled over an Haskell extension bug, or is there some point to this behavior?

like image 373
hgiesel Avatar asked Jul 31 '17 22:07

hgiesel


People also ask

What are type families in Haskell?

Indexed type families, or type families for short, are a Haskell extension supporting ad-hoc overloading of data types. Type families are parametric types that can be assigned specialized representations based on the type parameters they are instantiated with.

What is closed type family?

In GHC-7.7 (and 7.8) closed type families were introduced: A closed type family has all of its equations defined in one place and cannot be extended, whereas an open family can have instances spread across modules.


1 Answers

Yes, there is a subtle difference.

Roughly, type family F a :: *->* states that, say, F Int is an injective type constructor like [], Maybe. This is exploited by the compiler, which can type check the following code:

type family F a :: * -> *

-- these three examples can be removed / changed, if wished
type instance F Int = []
type instance F Char = Maybe
type instance F Bool = (,) String

foo :: (F Int a :~: F Int b) -> (a :~: b)
foo Refl = Refl

To type check the above, the compiler exploited the fact that F Int a ~ F Int b implies a ~ b, which follows from injectivity.

Instead, declaring type family F a b :: * does not ensure injectivity of F Int, since the following becomes legal.

type family F a b :: *
type instance F Int a = ()
like image 142
chi Avatar answered Sep 28 '22 20:09

chi