Estoy emulando un microprocesador de 4 bits. Necesito hacer un seguimiento de los registros, la memoria y el resultado de ejecución (puntos de bonificación por tener también un contador de ciclos de búsqueda y ejecución). He logrado hacer esto sin mónadas, pero se siente desordenado al pasar tantas cosas a la vez explícitamente. Además, la definición de la función es desordenada, larga y difícil de leer.Diferentes niveles de estado que interactúan en haskell
He intentado hacer esto con mónadas y simplemente no encaja. Traté de tratar todos los componentes de estado por separado como un solo tipo, pero eso me dejó con el problema de qué hacer con el valor.
State Program() -- Represents the state of the processor after a single iteration of the fetch execute cycle
Era el único tipo que tenía sentido. Pero en ese momento, ¿por qué molestarse? He intentado romper hacia arriba tirando de la cuerda de mi tipo de compuesto y tratándolo como el valor
State Program' String
el que funcionaba muy bien, excepto por el hecho de que necesitaba salida de RUNNING. No importaba lo que hiciera, no podía mantener tanto la cuerda como el estado al mismo tiempo.
Ahora estoy tratando de lidiar con transformadores de mónada. Parece que tengo que separar todos los diferentes niveles de estado. Pero mi cabeza está explotando rápido.
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))))
¡Ni siquiera he puesto en el contador FEcycle todavía!
Preguntas:
- estoy en el camino correcto?
- Al ver que estoy sacando transformadores de mónada ahora, ¿es posible dejar de tratar el "resultado de ejecución" como estado y simplemente llevarlo a la mónada IO? Eso sería increíble, en lugar de aferrarme a él, podría simplemente imprimirlo.
- ¿A cuántas capas debo separar el estado? Puedo ver dos capas distintas, pero dependen estrechamente unas de otras (tanto la memoria como los registros dependen del estado de la memoria y de los registros). ¿Debo mantenerlos juntos como un único estado o separarlos y apilarlos? ¿Qué enfoque producirá el código más legible?
Quizás la "salida en ejecución" se represente mejor usando la mónada Writer (ver http://monads.haskell.cz/html/writermonad.html)? –