The question says it all. More specifically, I am writing bindings to a C library, and I\'m wondering what c functions I can use unsafePerformIO
with. I assume
No need to involve C here. The unsafePerformIO
function can be used in any situation where,
You know that its use is safe, and
You are unable to prove its safety using the Haskell type system.
For instance, you can make a memoize function using unsafePerformIO
:
memoize :: Ord a => (a -> b) -> a -> b
memoize f = unsafePerformIO $ do
memo <- newMVar $ Map.empty
return $ \x -> unsafePerformIO $ modifyMVar memo $ \memov ->
return $ case Map.lookup x memov of
Just y -> (memov, y)
Nothing -> let y = f x
in (Map.insert x y memov, y)
(This is off the top of my head, so I have no idea if there are flagrant errors in the code.)
The memoize function uses and modifies a memoization dictionary, but since the function as a whole is safe, you can give it a pure type (with no use of the IO
monad). However, you have to use unsafePerformIO
to do that.
Footnote: When it comes to the FFI, you are responsible for providing the types of the C functions to the Haskell system. You can achieve the effect of unsafePerformIO
by simply omitting IO
from the type. The FFI system is inherently unsafe, so using unsafePerformIO
doesn't make much of a difference.
Footnote 2: There are often really subtle bugs in code that uses unsafePerformIO
, the example is just a sketch of a possible use. In particular, unsafePerformIO
can interact poorly with the optimizer.