如何正确更新Data.IORef中保存的Haskell记录?

时间:2018-05-07 20:27:59

标签: haskell

我有this simple project我尝试使用Haskell和Cairo库。

我遇到了重新绘制应用程序状态的问题。目前我拥有拥有全球状态的记录。我必须将它存储在Data.IORef monad中,以便能够将数据从一个GUI事件传递到另一个GUI事件。

我受到榆树的启发,尝试这样做,但我想知道是否有更好的方法可以做到这一点?

我特别关注主要功能中的这个片段。

-- update globalModel in place
readIORef globalModel >>= (\m -> writeIORef globalModel (Model
                                                         (fromIntegral kv)
                                                         (if ((keyToHeading (fromIntegral kv)) == None)
                                                           then (heading m)
                                                           else (keyToHeading (fromIntegral kv)))))

请提出更好的方法。

1 个答案:

答案 0 :(得分:4)

这可能是一个更简单的重构。请注意,modifyIORef'readIORefwriteIORef合并为一个严格的操作:

ifNoneThen :: Heading -> Heading -> Heading
None `ifNoneThen` x = x
h    `ifNoneThen` _ = h

updateModel :: Int -> Model -> Model
updateModel kv oldModel = Model newKv newHeading
    where newKv      = fromIntegral kv
          newHeading = keyToHeading newKv `ifNoneThen` heading oldModel

foo :: Int -> Model -> IO ()
foo kv globalModel = modifyIORef' globalModel (updateModel kv)
  • Header的一个小实用程序函数ifNoneThen(您也可以在其他地方使用)清除代码正文中的if语句。
  • 一些小的重构,以删除重复的调用(如果你可以调用一次并为结果提供一个有意义的名称,为什么要调用fromIntegral kv 3次?)。
  • 将纯代码(从旧模型中构建新模型)从不纯的代码(更新IORef)中分解出来,可以更容易地推理代码 - 意外副作用的地方更少突然出现。