How do I rewrite a Haskell function that uses modifyIORef' to use atomicModifyIORef'

223 views Asked by At

I am trying to solve a problem where Haskell gives different output to the same arguments. someone already has suggested that it could be a thread related issue.

I managed to rewrite a simple function to use the atomic version, but with more complex one I need help.

This is my code:

timeFun globalModel canvas = modifyIORef' globalModel (updateGlobalModel Tick) >> Gtk.widgetQueueDraw canvas >> return True

My findings

Following the advice I tried to rewrite the function using do notation:

timerFun g c = do
  i <- readIORef g
  writeIORef g (updateGlobalModel Tick i)
  Gtk.widgetQueueDraw c
  return True

Version that uses atomic code and do notation:

timerFun g c = do
  atomicModifyIORef' g $ \p -> do
    (updateGlobalModel Tick p ,())
  Gtk.widgetQueueDraw c
  return True
1

There are 1 answers

1
ruby_object On

The key to solving the problem was rewriting the function using do notation.

timerFun g c = do
  i <- readIORef g
  writeIORef g (updateGlobalModel Tick i)
  Gtk.widgetQueueDraw c
  return True

At this point I had writeIORef separated from other functions, so rewriting it using atomicModifyIORef' was trivial.

timerFun g c = do
  atomicModifyIORef' g $ \p -> 
    (updateGlobalModel Tick p, ())
  Gtk.widgetQueueDraw c
  return True

Same function with less syntactic sugar

timerFun g c = (atomicModifyIORef' g (\p -> (updateGlobalModel Tick p, ()))) >>
  Gtk.widgetQueueDraw c >>
  return True