2017-02-08 3 views
0

Ich bin nicht sehr gut hoskell programer. Ich bin beauftragt, einen Compiler an meiner Universität zu schreiben, und ich habe Haskell gewählt, weil es ein gutes Werkzeug für diesen Zweck ist. Ich bin mit StateT Monaden und außer, so habe ich Typen:Haskell StateT und ExceptT Kette

type Runner r s = StateT s (ExceptT LatteError IO) r 
type RT r s = IO (Either LatteError (r, s)) 

Ich benutze es schaffen, ein Programm Baum gehen und asm-Code zu erzeugen und es funktioniert, wie ich will. Als Hauptfunktion für das Gehen über Baum verwende ich

rProgram :: Program -> Runner [String] CompileState 

und Ergebnis auspacken Ich benutze Funktion

runR program = runExceptT (runStateT (rProgram program) initialCompileState) 

Was möchte ich nicht zu tun ist, um einige Validatoren zu haben, wie Typprüfung, ident existance Scheck, und ich weiß, sie zu schreiben. Lets sagen, ich

tcProgram :: Program -> Runner() TypeCheckState 
ieProgram :: Program -> Runner() IdentExistanceState 

haben will ich sie beide in eleganter Art und Weise ausgeführt werden, und ein Fehler wird durch throwError angegeben. Wie man viele Funktionen wie sie zusammenstellt?

+2

"Ich bin nicht sehr gut hoskell programer." Die Bereitschaft, diese Aufnahme bereits zu machen, sagt mir, dass Sie wahrscheinlich ein ziemlich guter Programmierer sind. – Alec

Antwort

4

lens hat einen zoom Kombinator, der eine Linse verwendet, um einen Teil des Zustands zu "zoomen".

zoom :: Lens' s t -> State t a -> State s a 

(Wie in lens üblich ist, ist die tatsächliche Art der zoom komplizierter als das, aber dies ist ein einfacher Weg, um darüber nachzudenken.)

So haben wir

zoom _1 . tcProgram :: Program -> Runner() (TypeCheckState, t) 
zoom _2 . ieProgram :: Program -> Runner() (s, IdentExistenceState) 

und so

liftA2 (>>) (zoom _1 . tcProgram) (zoom _2 . ieProgram) :: Program -> Runner() (TypeCheckState, IdentExistenceState) 
+0

Nur zu meiner Überlegung, wie LiftA2 zu ersetzen, wenn ich wie 5 Läufer haben möchte? –

+0

@ MichałPiotrStankiewicz Entweder schreiben Sie das Argument ('\ p -> tun {zoom _1 (tcProgram p); Zoom _2 (tcProgram p); etc}') oder kleben Sie ein ['ReaderT'] (https: //hackage.haskell .org/package/mtl-2.2.1/docs/Control-Monad-Reader.html) in Ihrem Monad-Transformer-Stack. –