Я пишу свой первый настоящий проект Haskell, и у меня возникли проблемы с организацией состояния в программе. Это эмулятор Gameboy Color, поэтому есть много маленьких флагов, и все состояние выглядит как
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.
Спасибо!