It's widely understood that unsafePerformIO is not type safe. This is typically demonstrated by using it to implement unsafeCoerce:
box :: IORef a
box = unsafePerformIO (newIORef undefined)
{-# NOINLINE box #-}
unsafeCoerce :: a -> b
unsafeCoerce a = unsafePerformIO $
writeIORef box a >> readIORef box
As I showed a few years ago, this implementation is not thread-safe. One thread could write to the box, and then another thread could write to the box again before the first thread can read. Oops! How can this be fixed?
As I showed once upon a time, the right way to do this is to use coercion through an
IORefto produce theunsafeCoercefunction itself, rather than to produce individual results of its application.