I have heard that various type system hacks in Haskell (unsafePerformIO
, Template Haskell, arbitrary-rank polymorphism,...) can be used to coerce different types, but I haven't seen the explicit implementations. How is it done, at least in GHC?
You can use unsafePerformIO
to create top-level IORef
s, i.e. mutable global variables. If you add polymorphism to this, you lose type safety as follows:
myVar :: IORef a -- polymorphic ref!
myVar = unsafePerformIO $ newIORef undefined
coerce :: a -> b
coerce x = unsafePerformIO $ do
writeIORef myVar x -- write value of type a
readIORef myVar -- read value of type b
Basically, a (non bottom) value of type forall a. IORef a
should not exist, ever. Its type states that you can use it as a mutable variable of the type you want, so you can write to it pretending it has one type, and then read from it pretending it has another type.
Note that monomorphic top-level IORef
s do not lead to type unsafety, since you can only write and read those at the same type.
Higher ranks are type safe, AFAIK.
I also do not know about Template Haskell.
Another source of type unsafety is user-written Typeable
instances, since those allow you to claim your own new datatype is actually an Int
and successfully use cast
to coerce values.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With