Version 10 (modified by 4 years ago) (diff) | ,
---|

# Kind-polymorphic `Typeable`

in GHC 7.8

The page describes an improved implementation of the `Typeable`

class, using polymorphic kinds, available from GHC 7.8. Technically it is straightforward, but it represents a non-backward-compatible change to a widely used library, so we had to make a plan for the transition.

Relevant tickets we fixed: #5391, #5863.

## The `Typeable`

class before 7.8

Before 7.8, the `Typeable`

class was as follows:

class Typeable (a :: *) where typeOf :: a -> TypeRep

Because it was mono-kinded we also had

class Typeable1 (f :: *->*) where typeOf1 :: f a -> TypeRep

and so on up to `Typeable7`

. It was a mess, and we couldn't make `Typeable`

at all for
type constructors with higher kinds like

Foo :: (* -> *) -> *

See #5391.

## The new `Typeable`

class, in GHC 7.8

Having polymorphic kinds lets us say this:

data Proxy t = Proxy class Typeable t where typeRep :: proxy t -> TypeRep

Notice that

`Typeable`

has a polymorphic kind:Typeable :: forall k. k -> Constraint

- The method is called
`typeRep`

rather than`typeOf`

- One reason for the name change is that the argument is not a value of the type
`t`

, but a value of type`(proxy t)`

. We have to do this because`t`

may have any kind, so we can't saytypeOf :: t -> TypeRep

- You can instantiate
`proxy`

to whatever you want; one common choice is the poly-kinded`Proxy`

datatype:Proxy:: forall k. k -> *

Now the base library code can have kind-specific instances:

instance Typeable Int where typeRep _ = ... instance Typeable [] where typeRep _ = ... instance (Typeable a, Typeable b) => Typeable (a b) where typeRep _ = ...

A use of `deriving( Typeable )`

for a type constructor `T`

always generates

instance Typable T where typeRep _ = ....

i.e. an instance of `T`

itself, not applied to anything.

## How to make your code compile again

If you have code involving `Typeable`

that fails to compile with 7.8, it might be due to the changes described above. Here's a few things to keep in mind in order to make your code compile again:

- Users can no longer giving manual instances of
`Typeable`

; they must be derived.

- Manual instances were often written for datatypes with non kind-
`*`

arguments. These can now be derived without problems. So if you had, for example:data Fix f = In (f (Fix f)) instance (Typeable1 f) => Typeable (Fix f) where typeOf = ...

you can now simply attach`deriving Typeable`

to`Fix`

.

- You can still use
`typeOf1..7`

; they are now just (deprecated) type-specific versions of`typeRep`

. But keep in mind that they are no longer methods of a class, as the classes`Typeable1..7`

no longer exist.

- You can still use
`Typeable1..7`

; they are now just (deprecated) type synonyms for`Typeable`

, fixing the kind of their argument. But keep in mind that they are no longer classes, just type synonyms.

- If all else fails, you could just try replacing your
`import Data.Typeable`

with`import Data.OldTypeable`

. But keep in mind that`OldTypeable`

is distinct, and incompatible with the new`Typeable`

.

- If you want code that compiles with multiple versions of GHC, you should use CPP. The tagged package on Hackage is a good example of how to achieve this.

## A change-over plan

**In GHC 7.8:**

- Rename
`Data.Typeable`

to`Data.OldTypeable`

and deprecate the whole module.

- Define a new library
`Data.Typeable`

with the new definitions in them.

- Include in
`Data.Typeable`

old methods for backward compatibility, but deprecate them:typeOf :: forall a. Typeable a => a -> TypeRep typeOf _ = typeRep (Proxy :: Proxy a) typeOf1 :: forall t (a :: *). Typeable t => t a -> TypeRep typeOf1 _ = typeRep (Proxy :: Proxy t) type Typeable1 (a :: * -> *) = Typeable a type Typeable2 (a :: * -> * -> *) = Typeable a

- Make
`deriving( Typeable )`

work with whatever`Typeable`

class is in scope. So what it does will be determined by whether you say`import Data.Typeable`

or`import Data.OldTypeable`

.

**In GHC 7.10:**

- Remove
`Data.OldTypeable`

## Aside

Open question: what are the corresponding changes to `Data.Data`

? See #4896.