Skip to content

Instantly share code, notes, and snippets.

@ppetr
Created September 10, 2012 19:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ppetr/3693348 to your computer and use it in GitHub Desktop.
Save ppetr/3693348 to your computer and use it in GitHub Desktop.
An example how to convert any type to any other using Haskell's unsafePerformIO
module CoerceUsingUnsafe where
import Data.IORef
import System.IO.Unsafe (unsafePerformIO)
import Data.Word
{- The trick behind this function is in the `test` experession.
When we create a new mutable variable in the IO monad,
it has a side effect of creating it somewhere in the memory.
If we work within the IO monad, it's all safe. Each time we
use an expression containing `newIORef` like `test` a new cell
in memory is allocated.
However, if we hide this side effect using `unsafePerformIO`, then
`test` behaves like a pure expression. If it is evaluated more than
once, its value is memoized. So each time we use `test`, we reference
the same memory cell it points to. But since `test` is polymorphic,
we can view the memory cell as having any type we choose.
-}
coerce :: a -> b
coerce x = unsafePerformIO $ do
writeIORef test [x]
[y] <- readIORef test
return y
where
test :: IORef [a]
test = unsafePerformIO $ newIORef []
main :: IO ()
main = do
-- Int coerced into Word
print (coerce (-1 :: Int) :: Word)
-- Function coerced into Int
print $ (coerce sqrt :: Int)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment