haskell - 如何正确更新 Data.IORef 中保存的 Haskell 记录?
问题描述
我有一个简单的项目,我尝试在其中尝试使用 Haskell 和 Cairo 库。
我在重绘应用程序状态时遇到了问题。目前我有保存全局状态的记录。我必须将它存储在Data.IORef
monad 中,以便能够将数据从一个 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)))))
请建议更好的方法。
解决方案
这可能是一个更简单的重构。请注意,modifyIORef'
将readIORef
and组合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)
Header
s 的一个小实用函数ifNoneThen
(您也可以在其他地方使用)清理if
代码主体中的语句。- 一些小的重构以删除重复的调用(
fromIntegral kv
如果你可以调用一次并给结果一个有意义的名称,为什么要调用 3 次?)。 - 从不纯代码中分解出纯代码(从旧模型构建新模型)(更新
IORef
.
推荐阅读
- c++ - FileNodeIterator opencv c++
- java - 终端上intellij IDEA上的jshell问题
- android - 无法绘制位图
- mysql - 日期过滤器在 magento 1 中无法正常工作
- linux - 为小米设备构建 linux 内核时出错
- angular - Angular 10:反应式表单不起作用
- flutter - 使用 Provider 避免在颤动中重建所有小部件树
- java - 如何在树莓派操作系统上安装 JavaFX
- java - 对 Dart 插件进行回调时,ScheduledExecutorThread 只执行一次
- javascript - 从动态列表中删除项目 ASP Core MVC