Estou tentando imprimir dentro da State
mônada usando liftIO
a função da MonadIO
classe:
import Control.Monad.State
import Control.Monad.IO.Class
import Control.Applicative
facHelper :: Integer -> State Integer ()
facHelper 0 = pure ()
facHelper n = do
currentState <- get
liftIO $ putStrLn $ "n = " ++ show currentState
modify (*n)
facHelper (n-1)
factorial :: Integer -> Integer
factorial n = snd (runState (facHelper n) 1)
main :: IO ()
main = print $ factorial 6
No entanto, recebo o erro:
Nenhuma instância para (MonadIO Data.Functor.Identity.Identity) resultante do uso de 'liftIO'
Se eu procurar MonadIO
classe:
Eu vejo uma instância:
MonadIO m => MonadIO (StateT s m)
E veja também que State s
é um alias de tipo
type State s = StateT s Identity
Então, em princípio, eu poderia usar liftIO
with State
. Onde está o problema ?
Se você quiser fazer isso
IO
,IO
deverá estar na parte inferior da pilha do transformador mônada. Esta é amtl
maneira usual de consertar as coisas:Isso usa
StateT Integer IO
em vez deState Integer
(ou sejaStateT Integer Identity
).Se você está curioso sobre os detalhes mecânicos do que deu errado com sua abordagem:
MonadIO (State s)
type State s = StateT s Identity
, portanto queroMonadIO (StateT s Identity)
MonadIO m => MonadIO (StateT s m)
, e mais especificamente tenhoMonadIO Identity => MonadIO (StateT s Identity)
, portanto queroMonadIO Identity
MonadIO Identity