unsafeCoerce coerces a value from one type to another, bypassing the type-checker.
There are several legitimate ways to use unsafeCoerce:
To coerce a lifted type such as
InttoAny, put it in a list ofAny, and then later coerce it back toIntbefore using it.To produce e.g.
(a+b) :~: (b+a)fromunsafeCoerce Refl. Here the two sides really are the same type -- so nothing unsafe is happening -- but GHC is not clever enough to see it.In
Data.Typeablewe have
eqTypeRep :: forall k1 k2 (a :: k1) (b :: k2).
TypeRep a -> TypeRep b -> Maybe (a :~~: b)
eqTypeRep a b
| sameTypeRep a b = Just (unsafeCoerce HRefl)
| otherwise = Nothing
Here again, the unsafeCoerce HRefl is safe, because the two types really
are the same -- but the proof of that relies on the complex, trusted
implementation of Typeable.
(superseded) The "reflection trick", which takes advantage of the fact that in
class C a where { op :: ty }, we can safely coerce betweenC aandty(which have different kinds!) because it's really just a newtype. Note: there is no guarantee, at all that this behavior will be supported into perpetuity. It is now preferred to usewithDictinGHC.Magic.Dict, which is type-safe. See Note [withDict] in GHC.Tc.Instance.Class for details.(superseded) Casting between two types which have exactly the same structure: between a newtype of T and T, or between types which differ only in "phantom" type parameters. It is now preferred to use
coercefromData.Coerce, which is type-safe.
Other uses of unsafeCoerce are undefined. In particular, you should not use
unsafeCoerce to cast a T to an algebraic data type D, unless T is also
an algebraic data type. For example, do not cast to Int->IntBool, even if
you later cast that Bool back to before applying it. The reasons
have to do with GHC's internal representation details (for the cognoscenti, data values
can be entered but function closures cannot). If you want a safe type to cast things
to, use Int->IntAny, which is not an algebraic data type.