
dons:
iavor.diatchki:
Hello, I think that it is a really bad idea to make 'unsafeCoerce' a part of the standard libraries. As far as I understand, 'unsafeCoerce' is only "safe" if the programmer assumes something about the representations of values (in particular, that values of different types have the same representations). Haskell makes no such guarantees so, by definition, any program that uses 'unsafeCoerce' is using an implementation specific extension. I was trying ot think of cases where 'unsafeCoerce' might be somewhat safe, and the main example I came up with is when the coersion happens on a phantom type. Are there other reasonably portable examples?
A quick grep in the core libraries, for insight: FFI stuff: ./base/Data/Array/Base.hs:678: nullStablePtr = StablePtr (unsafeCoerce# 0#) ./base/Data/Array/Base.hs:1522: case unsafeCoerce# memcpy marr'# marr# n# s2# of { (# s3#, () #) -> ./base/Data/Array/Base.hs:1592: case unsafeCoerce# memcpy marr# arr# n# s2# of { (# s3#, () #) -> ./base/Data/Array/Base.hs:1657: return (STUArray l u (unsafeCoerce# marr#)) Equalities not expressible in the type system: ./base/Data/Dynamic.hs:124: toDyn v = Dynamic (typeOf v) (unsafeCoerce v) ./base/Data/Dynamic.hs:135: | typeOf def == t = unsafeCoerce v ./base/Data/Dynamic.hs:147: case unsafeCoerce v of ./base/Data/Dynamic.hs:155: Just t3 -> Just (Dynamic t3 ((unsafeCoerce f) x)) ./base/Data/Typeable.hs:452: then Just $ unsafeCoerce x ./base/Data/Typeable.hs:460: then Just $ unsafeCoerce x ./base/Data/Typeable.hs:470: then Just $ unsafeCoerce x ./base/Data/Typeable.hs:480: then Just $ unsafeCoerce x I was actually surprised to see. That could be removed I'm pretty sure: ./base/Data/ByteString/Char8.hs:304: go :: Addr# -> [Char] -> ST a () go _ [] = return () go p (C# c:cs) = writeByte p (unsafeCoerce# c) >> go (p `plusAddr#` 1#) cs And some GHC things ./base/GHC/Handle.hs:1661: puts s = do write_rawBuffer 1 (unsafeCoerce# (packCString# s)) 0 (fromIntegral (length s)) ./base/GHC/ForeignPtr.hs:159: (# s, ForeignPtr (byteArrayContents# (unsafeCoerce# mbarr#)) ./base/GHC/ForeignPtr.hs:171: (# s, ForeignPtr (byteArrayContents# (unsafeCoerce# mbarr#)) ./base/GHC/ForeignPtr.hs:193: (# s, ForeignPtr (byteArrayContents# (unsafeCoerce# mbarr#)) ./base/GHC/ForeignPtr.hs:205: (# s, ForeignPtr (byteArrayContents# (unsafeCoerce# mbarr#)) ./base/GHC/ForeignPtr.hs:318: castForeignPtr f = unsafeCoerce# f And some FFI binding stuff: ./ObjectIO/Graphics/UI/ObjectIO/Process/IOState.hs:139: | ioStGetIOId ioSt == id = unsafeCoerce# (ps, ioSt) ./ObjectIO/Graphics/UI/ObjectIO/Window/Access.hs:578: | identifyWIDS wid wids = Just (unsafeCoerce# ls) So the uses fall into 2 categories: * FFI binding and raw pointer/foreign data manipulation * type equalities known, but not expressible statically Now, can we say something portable about these uses? -- Don