[Haskell-cafe] Memo + IORef

David House dmhouse at gmail.com
Sat Jun 16 08:27:07 EDT 2007

Tony Morris writes:
 > Yes, but where does the IORef live? Wouldn't I have to pass it back and
 > forth between invocations? If not, where do I get the IORef from on
 > subsequent invocations? Got a short example?

That's where the unsafePerformIO comes in. With unsafePerformIO and IORefs, you
can have global mutable variables:

{-# NOINLINE #-}
memo :: IORef Int
memo = unsafePerformIO (newIORef Nothing)

f = unsafePerformIO $ do
  ref <- readIORef memo
  case ref of
    Just val -> return val
    Nothing  -> let val = complexCalculation
                in writeIORef memo val >> return val

Something like that. If f took an argument then you'd probably use a IORef Map
or IORef IntMap or something in place of IORef Int. Be careful to:

1) Not break referential transparency. I.e. in my example, f will always return
the same value, how ever many times you call it. It's possible to break this
property using this trick.

2) Not use polymorphic references, as they lead to type unsafety [1].

3) Always use the {-# NOINLINE #-} pragma on any IORefs you create this way.

[1]: http://haskell.org/ghc/docs/latest/html/libraries/base/System-IO-Unsafe.html#v%3AunsafePerformIO

-David House, dmhouse at gmail.com

More information about the Haskell-Cafe mailing list