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 use withDict inGHC.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 coerce from
Data.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 Int->Int to Bool, even if
you later cast that Bool back to Int->Int 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 Any, which is not an algebraic data type.