Ответ 1
Линзы, безусловно, являются большой помощью для такого рода вещей, но вы предпочтете использовать их с большим, вложенным объектом чистого состояния в монаде State
, а не ST
. И я думаю, что это, вероятно, было бы хорошо для всех этих переменных, хотя это, вероятно, было бы неприемлемым для массивов (которые нужно было бы глубоко скопировать с каждой модификацией.
Итак, я мог бы подумать о двух вариантах:
- Переключение с массивов на структуру данных с эффективными чистыми функциональными обновлениями, например 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 и использовать линзы, чтобы удобно дойти до структуры. Сделав структуру более древовидной, обновления станут более эффективными. (Вероятно, вы также захотите распаковать те поля Word16
и Bool
, это действительно очень расточительно, чтобы хранить такие маленькие типы в коробке.)
Тем не менее, вы должны быть готовы к тому, что это не будет работать так же быстро, как аналогично сложная реализация, скажем, в С++. Чтобы достичь сопоставимой производительности, вам, вероятно, придется использовать все это состояние для использования одного STArray
, в котором закодирована вся информация о состоянии, и писать уродливые гейтеры и сеттеры в стиле OO в ST
, чтобы сделать его удаленно удобно.