Back to explicit Coercible instances?

Simon Peyton-Jones simonpj at
Sat Oct 12 12:12:35 UTC 2013

I don’t really agree.  Here's why:

The exact rules you suggest for when "deriving(Coercible)" would be allowed, are the rules we can use for when we need a "from thin air" instance.

Moreover, I'm very keen to give a simple, precise answer to the question
	if s is coercible to t
	when is (T s) coercible to (T t)
I propose that the answer is given by precisely T's roles.  At the moment I don't see why we would want to do anything more complicated.

But I'm open to being persuaded otherwise


| -----Original Message-----
| From: ghc-devs [mailto:ghc-devs-bounces at] On Behalf Of
| Joachim Breitner
| Sent: 12 October 2013 11:52
| To: ghc-devs at
| Subject: Back to explicit Coercible instances?
| Hi,
| the recent discussion about roles and abstraction lets me wonder
| whether
| we should re-evaluate the question of where the Coercible instances
| come
| from.
| Currently, upon use of "coerce", GHC will create Coercible instances
| out
| of thin air, as long as the roles agree, and checking some
| constructor-in-scope invariants. This is troublesome WRT. abstraction.
| One alternative that was discussed before is explicit Coercible
| instances. That is, if I write a datatype
|         datatype MyList a = Cons a (MyList a) | MyNil
| then I have to explicitly write either
|                 deriving Coercible
| to get
|         instance Coercible a b => Coercible (MyList a) (MyList b)
| or – especially if I want to control which parameters are coercible –
| have to use standalone deriving and write
|         deriving instance Coercible a b => Coercible (MyList a) (MyList
|         b)
| For something like Set, the user would not use “deriving Coercible”,
| but
| would use
|         deriving instance Coercible a b => Coercible (Set k a) (Set k
| b)
| Manual instances of Coercible would be prohibited. The instances are
| checked for things like:
|  * do the roles allow the behaviour?
|  * are the constructors in scope (for standalone deriving)?
|  * are the arguments of the constructors coercible?
| The last check ensures that the user cannot break abstraction by
| wrapping an abstract datatype in a datatype of its own. But note that
| these instances (between the datacon argument types) are only checked,
| never actually used! Therefore we must sure that only sound instances
| exists, and that the user cannot bogus instances (e.g. one with all
| fields undefined).
| This would imply a few differences:
|  * Already for syntactical reasons, there will be no instances for
| coercing constraints. As we have seen, this is a good thing.
|  * Would be no way to use a coercion within the abstraction boundaries,
| but not outside, because you either have the instance, or you don’t.
| And assuming GND would simply implement its classes by passing each
| method through "coerce", this would hopefully also yield a sensible
| design for GND.
| Greetings,
| Joachim
| --
| Joachim “nomeata” Breitner
|   mail at joachim-breitner.de
|   Jabber: nomeata at  • GPG-Key: 0x4743206C
|   Debian Developer: nomeata at

More information about the ghc-devs mailing list