SwirlyMyself

2013-09-14T10:35:19+00:00

Adding safe coercions to Haskell

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 a and 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 Age and 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.

Comments

Oh, this is wonderful! Great work!
#1 Brent Yorgey (Homepage) am 2013-09-14T20:35:50+00:00
Really? I’m very curious about real use cases :-)
#2 Joachim Breitner (Homepage) am 2013-09-14T21:55:37+00:00
I've been looking forward to abusing these. In particular in lens we have a whole pile of hacks to get decent performance using unsafeCoerces that are all actually legitimate uses of coerce.

The only tedious part is we'll have to rename our own `coerce` combinator. ;)
#3 Edward Kmett (Homepage) am 2013-09-15T18:27:50+00:00

Have something to say? You can post a comment by sending an e-Mail to me at <mail@joachim-breitner.de>, and I will include it here.