gpt4 book ai didi

haskell - 如何在 Haskell 项目中组织大量状态

转载 作者:行者123 更新时间:2023-12-04 02:20:46 26 4
gpt4 key购买 nike

我正在编写我的第一个真正的 Haskell 项目,并且在程序中组织状态时遇到了麻烦。这是一个Gameboy Color模拟器,所以有很多小flag,整个状态看起来像

data Memory s = Memory { memory :: STUArray s Word16 Word8
, registers :: STUArray s Word8 Word8
, sp :: STRef s Word16
, pc :: STRef s Word16
, cycles :: STRef s Word16
, ime :: STRef s Bool --Interrupt Master Enable Flag
, halt :: STRef s Bool --Are we halted or not
, mode :: STRef s GPUMode -- GPU mode
, line :: STRef s Word8 -- GPU line
, transferred :: STRef s Bool
, gpuCycles :: STRef s Word16
, window :: Window
, renderer :: Renderer
}

我对状态进行所有读/写,例如:
 data Address = OneRegister Register
| TwoRegister {registerA :: Register, registerB :: Register}
| MemAddr Word16
| SP
| PC
| CYCLES
| IME
| HALT_STATE
| GPU_MODE
| GPU_LINE
| GPU_TRANSFERRED_LINE
| GPU_CYCLES

data MemVal = MemVal8 Word8
| MemVal16 Word16
| Flag Bool
| Mode GPUMode

read :: Memory s -> Address -> ST s MemVal
write :: Memory s -> Address -> MemVal -> ST s ()

你可以看到: https://github.com/nikhilunni/HaskellBoy/blob/master/src/Memory.hs

有什么更简洁的方法可以让我组织一切吗?如果可能的话,我想在各种组件(CPU、GPU、磁带库切换等)之间划分状态。在 Haskell 中有一个大的单片状态类型是惯用的吗?

向程序添加新状态是一个相当大的痛苦。 Control.Lens 包似乎是正确的,但我不确定我是否可以很容易地将它与 ST 结合起来。

谢谢!

最佳答案

镜头对这类东西绝对有很大帮助,但你更愿意将它们与 State 中的大型嵌套纯状态对象一起使用。 monad,而不是 ST .而且我认为这对于所有这些变量可能都可以,尽管对于数组来说可能是 Not Acceptable (每次修改都需要深度复制。

所以我可以想到两个选择:

  • 从数组切换到具有高效纯函数更新的数据结构,例如 Sequence .抛弃那些STRefs完全赞成 State 中基于镜头的更新.这不会像 ST 中的破坏性数组更新那样有效,但如果要在快速的现代计算机上模拟 Game Boy,它可能会起作用。
  • 拆分内存类型,以便您可以将数组保存在 ST 中,但将所有其他状态组合在一个 STRef 中到纯数据结构。然后你可以使用镜头。
    data Memory s = Memory { memory :: STUArray s Word16 Word8
    , registers :: STUArray s Word8 Word8
    , memRefs :: STRef s MemRefs
    , window :: Window
    , renderer :: Renderer
    }

    data MemRefs = MemRefs { _sp :: Word16
    , _pc :: Word16
    , _cycles :: Word16
    , _ime :: Bool --Interrupt Master Enable Flag
    , _halt :: Bool --Are we halted or not
    , _mode :: GPUMode -- GPU mode
    , _line :: Word8 -- GPU line
    , _transferred :: Bool
    , _gpuCycles :: Word16
    }
    mkLenses ''MemRefs

  • 好消息是,您现在可以对 MemRef 进行分组。输入 al gusto,并使用镜头方便地伸入结构中。通过使结构更像树,更新实际上会变得更有效率。 (您可能还想拆箱 Word16Bool 字段,将这么小的类型装箱真的很浪费。)

    即便如此,您也应该做好准备,它不会像 C++ 中类似复杂的实现那样运行得那么快。要获得可比较的性能,您可能必须手动修改所有状态以使用单个 STArray其中所有状态信息都被编码,并在 ST 中编写丑陋的 OO 风格的 getter 和 setter使其远程方便。

    关于haskell - 如何在 Haskell 项目中组织大量状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34781651/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com