2017-02-08 15 views
0

Я не очень хороший программатор haskell. Мне поручено написать компилятор в моем университете, и я выбрал haskell, так как это хороший инструмент для этой цели. Я использую монады StateT и за исключением, так что я типа:Haskell StateT и ExceptT chain

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

Я использую его создать ходить дерево программы и производить код ассемблера, и она работает, как я хочу. В основной функции для подходя дерева я использую

rProgram :: Program -> Runner [String] CompileState 

и распаковывать результат я использую функцию

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

То, что я хочу сделать, не иметь некоторые валидатор, как проверка типа, идент проверка существования, и я знаю, чтобы написать их. Позволяет сказать, у меня есть

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

Я хочу, чтобы запустить их обоих в элегантно, и отказ обозначается throwError. Как ставить многие функции, подобные им вместе?

+2

«Я не очень хороший программник haskell». Готовность сделать это признание уже говорит мне, что вы, вероятно, довольно хороший программист. – Alec

ответ

4

lens имеет комбинатор zoom, который использует объектив для «увеличения масштаба» на части состояния.

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

(как обычно в lens, фактический тип zoom является более сложным, чем это, но это простой способ думать об этом.)

Таким образом, мы имеем

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

и так

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

Только к моему рассмотрению, как заменить liftA2, если я хочу иметь как 5 бегунов? –

+0

@ MichałPiotrStankiewicz Либо выпишите аргумент ('\ p -> do {zoom _1 (tcProgram p), zoom _2 (tcProgram p) и т. Д.) Или вставьте [' ReaderT'] (https: //hackage.haskell .org/package/mtl-2.2.1/docs/Control-Monad-Reader.html) в вашем стеке трансформатора монады. –