coerce error when role is nominal could be more explicit
Motivation
If a type Foo a
have a type parameter a
with role
nominal
, it's not possible to coerce
it to Foo b
, even if a
and b
are Coercible
. That's the definition of the role system.
However, the error message associated with it are not helpful.
For example, consider the following example:
{-# LANGUAGE RoleAnnotations #-}
import Data.Monoid (Sum(..))
import Data.Coerce (coerce)
type role Foo nominal
data Foo a = Foo a
deriving (Ord, Eq)
foo :: Foo Int
foo = coerce (Foo (10 :: Sum Int))
With ghc 9.6, it fails with:
GHCi, version 9.6.2: https://www.haskell.org/ghc/ :? for help
[1 of 2] Compiling Main ( V.hs, interpreted )
V.hs:20:8: error: [GHC-18872]
• Couldn't match type ‘Sum Int’ with ‘Int’
arising from a use of ‘coerce’
• In the expression: coerce (Foo (10 :: Sum Int))
In an equation for ‘foo'’: foo' = coerce (Foo (10 :: Sum Int))
|
20 | foo' = coerce (Foo (10 :: Sum Int))
Removes the type role
annotations, and that's fine. Note how the error message does not reference the role
system, or representational
or nominal
at all. It does not reference Foo
at all, even if the problem is actually not with matching the type Sum Int
and Int
. Even the wording match
is confusing.
Here is a second example, which is actually the real life example which annoyed me recently. In vector
latest version, Data.Vector.Storable
role annotation changed to nominal
, hence it is not possible anymore to coerce
between two Vector
.
{-# LANGUAGE RoleAnnotations #-}
import Data.Monoid (Sum(..))
import Data.Coerce (coerce)
import Data.Vector.Storable
foo :: Vector (Sum Int)
foo = coerce (empty :: Vector Int)
However, the error message:
GHCi, version 9.6.2: https://www.haskell.org/ghc/ :? for help
[1 of 2] Compiling Main ( V.hs, interpreted )
V.hs:7:7: error: [GHC-18872]
• Couldn't match type ‘Int’ with ‘Sum Int’
arising from a use of ‘coerce’
• In the expression: coerce (empty :: Vector Int)
In an equation for ‘foo’: foo = coerce (empty :: Vector Int)
|
7 | foo = coerce (empty :: Vector Int)
Does not give any clue about the root cause for the problem. See, here, no notion of role
or Vector
. This was particularly vicious for me because when bumping from GHC 9.6.1
to 9.6.2
, I got the vector
version bump at the same time and got this error message on multiples places in my codebase.
Note that GHC is correct with the error, just that the wording can be improved with more context.
Proposal
I suggest to improve the wording to at least include a reference to coerce
, the role
annotation, nominal
, and pointing at the Vector
type. For example, I'll be happy with:
GHCi, version 9.6.2: https://www.haskell.org/ghc/ :? for help
[1 of 2] Compiling Main ( V.hs, interpreted )
V.hs:7:7: error: [GHC-18872]
• Couldn't coerce type `Vector Int` with `Vector (Sum Int)`
arising from a use of ‘coerce’ because of role annotation `type role Vector nominal`.
• In the expression: coerce (empty :: Vector Int)
In an equation for ‘foo’: foo = coerce (empty :: Vector Int)
|
7 | foo = coerce (empty :: Vector Int)