Я эмулирую 4-битный микропроцессор. Мне нужно отслеживать регистры, память и текущий результат (бонусные баллы за наличие счетчика циклов выборки-выполнения). Мне удалось сделать это без монад, но я чувствую себя грязно, передавая столько всего сразу. Также определение функции грязное, длинное и трудно читаемое.
Я пытался сделать это с монадами, и это просто не подходит друг другу. Я пытался рассматривать все отдельные компоненты состояния как один тип, но у меня осталась проблема с тем, что делать со значением.
State Program () -- Represents the state of the processor after a single iteration of the fetch execute cycle
Был единственный тип, который имел какой-либо смысл. Но в тот момент, зачем вообще беспокоиться? Я попытался разбить его, вытащив строку из моего составного типа и обработав ее как значение
State Program' String
, который работал отлично, за исключением того факта, что мне нужен выход RUNNING. Что бы я ни делал, я не мог одновременно удерживать строку и состояние.
Теперь я пытаюсь разобраться с монадными трансформаторами. Кажется, что я должен выделить все различные уровни государства. Но моя голова быстро взрывается.
StateT Registers (StateT Memory (State Output)) a =
StateT (registers -> (StateT Memory (State Output)) (a,registers))
StateT Registers (StateT Memory (State Output)) a =
StateT (registers -> (Memory -> (Output -> (((a,Registers),Memory),Output))))
Я еще даже не включил счетчик FEcycle!
Вопросы:
- Я на правильном пути?
- Видя, как я сейчас вытаскиваю монадные трансформаторы, можно ли перестать воспринимать «работающий выход» как состояние и просто подсунуть его монаде ввода-вывода? Это было бы здорово, вместо того, чтобы держаться за него, я мог бы просто напечатать его.
- На сколько слоев я должен разделить состояние? Я вижу два разных уровня, но они тесно зависят друг от друга (и память, и регистры зависят от состояния как памяти, так и регистров). Должен ли я хранить их вместе как одно государство или отделять их и складывать? Какой подход даст наиболее читаемый код?