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 Int to Any, put
it in a list of Any, and then later coerce it back to
Int before using it.
- To produce e.g. (a+b) :~: (b+a) from unsafeCoerce
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.Typeable we 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 between C a and ty (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 in
GHC.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.