[Haskell-cafe] What is the right way to use unsafeCoerce?

Cosmia Fu cosmiafu at gmail.com
Tue Aug 14 04:05:37 UTC 2018

Thanks a lot!

Cosmia Fu

On Tue, Aug 14, 2018 at 12:00 PM Brandon Allbery <allbery.b at gmail.com> wrote:
> unsafeCoerce just tells the typechecker to use a different type for that value. Values of all types as stored in memory have pretty much the same basic layout: constructor tag as an Int# counting upward from 0 per type, followed by a pointer for each associated value (or the actual value if it's unboxed; so an Int is stored as an 0# followed by an Int# representing its value), each of these consuming a single basic word (64 bits on a 64-bit platform). So a Bool is the same as an Int# which is 0# or 1#, and for an Either String Int you have a constructor tag 0# for Left or 1# for Right, followed by a single pointer whose associated type is determined by the constructor tag (here, either it points to a String or to an Int).
> Unpacking and/or unboxing values can alter this and complicate things. See the GHC manual with respect to the UNPACK pragma and -funbox-strict-fields; you may under some circumstances need to disable optimization if you want to (ab)use unsafeCoerce.
> So in short, info tables don't usually come into play at this level. But you can cause core dumps if you're not careful, especially if you do something like coercing a value from a type with 2 constructors to a type that has only 1. It is, however, safe if you ensure the runtime representation of values of both types are the same (but as above, ensuring this sometimes means compiling without optimization).
> On Mon, Aug 13, 2018 at 10:47 PM Cosmia Fu <cosmiafu at gmail.com> wrote:
>> Hi all,
>> I have noticed that unsafeCoerce is able to
>> > Prelude> import Unsafe.Coerce
>> > Prelude Unsafe.Coerce> data P = P Int Double deriving Show
>> > Prelude Unsafe.Coerce> data Q a b = Q a b deriving Show
>> > Prelude Unsafe.Coerce> unsafeCoerce (P 23 2.33) :: Q Int Double
>> > Q 23 2.33
>> And it works even for sum type, and the first constructor always wins.
>> > Prelude Unsafe.Coerce> data M a = J a deriving Show
>> > Prelude Unsafe.Coerce> unsafeCoerce (J "qwe") :: Either String String
>> > Left "qwe"
>> > Prelude Unsafe.Coerce> unsafeCoerce (Just "qwe") :: M String
>> > J "qwe"
>> And the documenation for unsafeCoerce# says
>> > Casting between two types that have the same runtime representation. One case is when the two types differ only in "phantom" type parameters, for example Ptr Int to Ptr Float, or [Int] to [Float] when the list is known to be empty. Also, a newtype of a type T has the same representation at runtime as T.
>> > http://hackage.haskell.org/package/base-
>> But info tables for different constructors are different. Why does the
>> code above work?
>> And is it safe to use unsafeCoerce like this?
>> Thanks,
>> Cosmia Fu
>> _______________________________________________
>> Haskell-Cafe mailing list
>> To (un)subscribe, modify options or view archives go to:
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>> Only members subscribed via the mailman list are allowed to post.
> --
> brandon s allbery kf8nh
> allbery.b at gmail.com

More information about the Haskell-Cafe mailing list