Question

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?

Was it helpful?

Solution

On unsafePerformIO

You can use unsafePerformIO to create top-level IORefs, 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 IORefs do not lead to type unsafety, since you can only write and read those at the same type.

On others

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top