Use of evaluate in Control.Concurrent.MVar

David Feuer david.feuer at gmail.com
Mon Oct 12 18:01:30 UTC 2020


Control.Concurrent.MVar uses `evaluate` in a couple places, and I
don't understand why:

modifyMVar :: MVar a -> (a -> IO (a,b)) -> IO b
modifyMVar m io =
  mask $ \restore -> do
    a      <- takeMVar m
    (a',b) <- restore (io a >>= evaluate) `onException` putMVar m a
    putMVar m a'
    return b

modifyMVarMasked :: MVar a -> (a -> IO (a,b)) -> IO b
modifyMVarMasked m io =
  mask_ $ do
    a      <- takeMVar m
    (a',b) <- (io a >>= evaluate) `onException` putMVar m a
    putMVar m a'
    return b

The general purpose is to make sure that the result of the IO action
is forced to head normal form within the scope of the `catch` block
created by `onException`. But in this context, I don't see why we need
to use `evaluate` rather than just `seq`, or why that is desirable.
Couldn't we just do this?

modifyMVar m io =
  mask $ \restore -> do
    a      <- takeMVar m
    (a',b) <- restore (io a >>= (pure $!)) `onException` putMVar m a
    putMVar m a'
    return b

David


More information about the Libraries mailing list