
Hi, Am Mittwoch, den 13.12.2017, 21:34 -0800 schrieb Evan Laforge:
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.
this coercion is not possible in Core, because Core’s type system is not expressive enough (at least now…). But luckily, at the STG level this optimization is possible, see https://git.haskell.org/ghc.git/commitdiff/19d5c7312bf0ad9ae764168132aecf369... This is probably in 8.2. Joachim -- Joachim Breitner mail@joachim-breitner.de http://www.joachim-breitner.de/