Joachim Breitner's Homepage
Yesterday, I pushed my first sizable contribution to GHC, the Haskell compiler. The feature solves the problem that newtypes are not always free: If we have
newtype Age = MkAge Int, then we have all learned that the
Age function has zero run-time cost. But if the
Int that we want to convert is inside another type, the conversion is no longer free: Converting a
Maybe Int to a
Maybe Age using, for example,
fmap Age, will cause time and space overhead at runtime, and there was no way around it. Well, there is
unsafeCoerce, but really, that ought to be avoided.
So after some discussion with and encouragement of Simon Peyton Jones at RDP in Eindhoven this year I worked on a design (which was developed, as far as I know, by Simon, Roman Cheplyaka, Stephanie Weirich, Richard Eisenberg and me). In GHC 7.8, there will be a function
coerce :: Coercible a b => a -> b that works, from the user point of view, like
unsafeCoerce (i.e. no run-time cost), but with the big difference that it will only typecheck if the compiler can infer that it indeed is safe to coerce between
b. So it will derive
Coercible Age Int, and
Coercible Int Age, and
Coercible (Maybe Age) (Maybe Int) and even stuff like
Coercible (Int -> Age) (Age -> Int), but not
Coercible Int Bool. It will also not coerce between
Int if the constructor
MkAge is not exported, to respect module boundaries.
Under the hood this relies on the also new feature of roles, which were solved to make the previously unsafe
GeneralizedNewtypeDeriving feature safe again, and which also guarantee that
coerce is indeed as safe as the name suggests.
The feature will come with 7.8, but not “fully advertised”, so things might change again for 7.10, and bugs with the feature may not necessarily qualify to be fixed in further 7.8.x releases, so beware. It also does not automatically convert
fmap Age into
coerce, but it is a step in that direction.