Data.Type.Equality and coercions

Simon Peyton-Jones simonpj
Thu Oct 10 09:59:10 UTC 2013

I?m afraid that ?subst? really isn?t a good name.

coerce :: Coercible a b => a -> b
coerceWith :: Coercion a b -> a -> b

cast :: forall a b. (Typeable a, Typeable b) => a -> Maybe b

So ?cast? is to do with genuine, nominal type equality.    With that in mind, how about

castWith :: (a :~: b) -> a -> b


From: Libraries [mailto:libraries-bounces at] On Behalf Of Edward Kmett
Sent: 09 October 2013 18:19
To: Richard Eisenberg
Cc: Joachim Breitner; Haskell Libraries
Subject: Re: Data.Type.Equality and coercions

I sent Austin a patch about 4 hours before your post that included the code for the resolution to the (:~:) vs (==) Proposal that included a renaming of Data.Type.Equality.coerce.

Notably, the core libraries committee decided to take Simon's suggestion that the witness should be (:~:) rather than (:=:), and I observed that (==) was never the right name, because (a <= b) is a constraint, but a data type, which removed any objections I had.

As a knock-on effect of that discussion, I implemented a Category for Data.Type.Coercion. (It turned out to be trivially implementable with the existing Coercible with no changes needed, by borrowing some tricks from my old eq package) and wound up needing to import Data.Type.Equality inside it and noticed the conflict.

I renamed 'Data.Type.Equality.coerce' it to 'subst' somewhat arbitrarily, though, as we're getting down close to the wire and we're starting to try to avoid base exporting multiple functions with the same name but different signatures to reduce confusion.

If you still want this bikeshed to have a different color, by all means carry on!

'subst' may be a better name for gcoerce than it is for coerce, anyways, so there is plenty of room for discussion.


On Wed, Oct 9, 2013 at 11:25 AM, Richard Eisenberg <eir at<mailto:eir at>> wrote:
I've noticed two infelicities with the Data.Type.Equality module that I added this summer (according to this proposal:  For those of you unfamiliar, the key definition is this:

> data a :=: b where
>   Refl :: a :=: a

This is essentially just like (~), but in * instead of Constraint.

1. There is a function
> coerce :: (a :=: b) -> a -> b

This function conflicts with the new function of the same name in the Coercible class (defined in GHC.Prim), with the type
> coerce :: Coercible a b => a -> b

So, these functions are very similar. The first uses explicit nominal equality, while the second uses implicit representational equality. Neither quite subsumes the other.

(Disclaimer: I may or may not have named both of these myself, albeit separated by several months. If I did, sorry for creating this problem.)

My slight inclination: rename the Coercible version to `coerceRep`, as it really is doing a runtime coercion, as opposed to `coerce`. But, I'm quite happy for someone else to have a better idea.

2. There is a useful function that should be added to Data.Type.Equality:

> gcoerce :: (a :=: b) -> ((a ~ b) => r) -> r
> gcoerce Refl x = x

For an example of this in action, see, which is related to #8423 but can be read standalone.

I don't think that gcoerce can subsume coerce because they have different type inference implications. In particular, the types of the coercion in `coerce` can improve the type of the equality witness, whereas this is not possible in `gcoerce`.

Discussion time: 1 week.


Libraries mailing list
Libraries at<mailto:Libraries at>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the Libraries mailing list