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

如何正确更新Data.IORef中保存的Haskell记录?,haskell,Haskell,我曾经尝试过Haskell和开罗图书馆 我在重新绘制应用程序的状态时遇到问题。目前,我有记录,持有全球国家。我必须将它存储在Data.IORefmonad中,以便能够将数据从一个GUI事件传递到另一个GUI事件 我是受Elm的启发尝试这样做的,但我想知道是否有更好的方法 我特别关注main函数中的这个片段 -- update globalModel in place readIORef globalModel >>= (\m -> writeIORef globalModel

我曾经尝试过Haskell和开罗图书馆

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

我是受Elm的启发尝试这样做的,但我想知道是否有更好的方法

我特别关注main函数中的这个片段

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

请建议更好的方法。

这可能是一个更简单的重构。请注意,将
readIORef
writeIORef
组合成一个严格的操作:

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)
  • 一个用于
    标题
    s的小型实用程序函数,
    ifnoneten
    (您也可以在其他地方使用)清理代码主体中的
    if
    语句
  • 一些小的重构来删除重复的调用(如果可以调用一次并给结果起一个有意义的名字,为什么要调用
    fromIntegral kv
    3次?)
  • 将纯代码(从旧模型构建新模型)从非纯代码(更新
    IORef
    )中分解出来,可以更容易地对代码进行推理-出现意外副作用的地方更少

IORef
不是monad。它表明我是noob:-)为什么不考虑从
IORef
业务中更改模型?后者类似于
modifyIORef'
。非常感谢。今天我学到了关于Haskell的新东西。在某些情况下,使用modifyIORef会导致问题@ruby_object这是对原始代码的语义等效重构(避免在新模型中过于严格)-听起来多线程不是您原始问题的考虑因素。