Combinar estado com ações de E / S

Suponha que eu tenha uma mônada de estado como:

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)

com funções como

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

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

e assim por diante. Quero combinar várias operações nesta mônada com ações de E / S. Então, eu poderia escrever um loop de avaliação no qual as operações nessa mônada foram executadas e uma ação de E / S é executada com o resultado ou, penso, eu deveria poder fazer algo como o seguinte:

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

As funções de impressão teriam o tipo Op () e outras funções teriam o tipo Op a, por exemplo, eu poderia ler um caractere do terminal usando uma função do tipo IO Char. No entanto, não tenho certeza de como seria essa função, pois, por exemplo, o seguinte não é válido.

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

desde que getLine possui o tipo IO Char, mas essa expressão teria o tipo Op Char. Em resumo, como eu faria isso?

questionAnswers(2)

yourAnswerToTheQuestion