Sto emulando un microprocessore a 4 bit. Ho bisogno di tenere traccia dei registri, della memoria e dell'output in esecuzione (punti bonus per avere anche un contatore di cicli fetch-execute). Sono riuscito a farlo senza monade, ma mi sembra complicato passare così tante cose contemporaneamente in modo esplicito. Anche la definizione della funzione è disordinata, lunga e difficile da leggere.Diversi livelli di stato interagenti in haskell
Ho provato a farlo con le Monade e semplicemente non combacia. Ho provato a trattare tutti i componenti di stato separati come un singolo tipo, ma questo mi ha lasciato il problema di cosa fare il valore.
State Program() -- Represents the state of the processor after a single iteration of the fetch execute cycle
Era l'unico tipo che aveva senso. Ma a quel punto perché preoccuparsi? Ho provato diffondendola tirando la stringa dal mio tipo composito e trattandolo come valore
State Program' String
che funzionava bene, tranne per il fatto che mi serviva uscita RUNNING. Non importa quello che ho fatto, non potevo aggrapparmi alla stringa e allo stato contemporaneamente.
Ora sto provando a cimentarmi con i trasformatori monad. Sembra che devo separare tutti i diversi livelli di stato. Ma la mia testa sta esplodendo velocemente.
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))))
Non ho ancora inserito il contatore di FEcycle!
Domande:
- Sono sulla strada giusta?
- Visto che sto estraendo i trasformatori monad ora, è possibile smettere di trattare "l'uscita in esecuzione" come stato e trasferirlo alla monade IO? Sarebbe fantastico, invece di aggrapparmici potrei semplicemente stamparlo.
- Quanti layer dovrei separare in stato? Riesco a vedere due strati distinti, ma dipendono l'uno dall'altro da vicino (sia la memoria che i registri dipendono dallo stato sia della memoria che dei registri). Dovrei tenerli insieme come un singolo stato o separarli e impilarli? Quale approccio produrrà il codice più leggibile?
Forse "l'uscita in esecuzione" potrebbe essere rappresentata al meglio utilizzando la monade Writer (consultare http://monads.haskell.cz/html/writermonad.html)? –