[Haskell-cafe] coercing D a to D b

Evan Laforge qdunkan at gmail.com
Thu Dec 14 05:34:13 UTC 2017


Given:

data D a = A a | B Int Char

dmapNoCoerce :: (a -> b) -> D a -> D b
dmapNoCoerce f (A a) = A (f a)
dmapNoCoerce _ (B i c) = B i c

I have to reconstruct a B change it from D a to D b.  But at the lower level,
couldn't this be implemented as a type cast?  What prevents such an
optimization?

I can write this as

dmapCoerce :: (a -> b) -> D a -> D b
dmapCoerce f (A a) = A (f a)
dmapCoerce _ b@(B {}) = Unsafe.Coerce.unsafeCoerce b

>From the core, it looks like dmapCoerce indeed has a cast with no allocation,
while dmapNoCoerce allocates a new B.

It seems to work, but is it safe?  Is there a more principled way to do it?
I can't convince Data.Coerce to cooperate, presumably because 'a' and 'b' are
not coercible themselves, and it doesn't believe me if I try to tell it the
type role is phantom.


More information about the Haskell-Cafe mailing list