Объединить состояние с действиями ввода-вывода

Предположим, у меня есть монада состояний, такая как:

data Registers = Reg {...}

data ST = ST {registers :: Registers,
              memory    :: Array Int Int}

newtype Op a = Op {runOp :: ST -> (ST, a)}

instance Monad Op where
 return a    = Op $ \st -> (st, a)
 (>>=) stf f = Op $ \st -> let (st1, a1) = runOp stf st
                               (st2, a2) = runOp (f a1) st1
                            in (st2, a2)

с такими функциями, как

getState :: (ST -> a) -> Op a
getState g = Op (\st -> (st, g st)

updState :: (ST -> ST) -> Op ()
updState g = Op (\st -> (g st, ()))

и так далее. Я хочу объединить различные операции в этой монаде с действиями ввода-вывода. Так что я мог бы написать цикл оценки, в котором выполнялись операции в этой монаде и выполнялось действие ввода-вывода с результатом, или, я думаю, Я должен быть в состоянии сделать что-то вроде следующего:

newtype Op a = Op {runOp :: ST -> IO (ST, a)}

Функции печати будут иметь тип Op (), а другие функции будут иметь тип Op a, например, я мог бы читать символ из терминала, используя функцию типа IO Char. Однако я не уверен, как будет выглядеть такая функция, поскольку, например, следующее недопустимо:

runOp (do x <- getLine; setMem 10 ... (read x :: Int) ... ) st

, поскольку getLine имеет тип IO Char, но это выражение будет иметь тип Op Char. В общих чертах, как мне это сделать?

28
задан danportin 4 September 2010 в 00:49
поделиться