我尝试State
使用类liftIO
中的函数在 monad 内打印MonadIO
:
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
但是,我收到错误:
没有因使用“liftIO”而产生的 (MonadIO Data.Functor.Identity.Identity) 实例
如果我查找MonadIO
班级:
我看到一个例子:
MonadIO m => MonadIO (StateT s m)
并且还看到这State s
是一个类型别名
type State s = StateT s Identity
所以,原则上,我可以使用liftIO
with State
。哪里有问题 ?
如果你想这样做
IO
,那么IO
必须位于你的 monad 变压器堆栈的底部。mtl
这是修复问题的常用方法:这使用
StateT Integer IO
而不是State Integer
(即StateT Integer Identity
)。如果您对您的方法出了问题的机械细节感到好奇:
MonadIO (State s)
type State s = StateT s Identity
,所以想要MonadIO (StateT s Identity)
MonadIO m => MonadIO (StateT s m)
,更具体地说有MonadIO Identity => MonadIO (StateT s Identity)
,因此想要MonadIO Identity
MonadIO Identity