haskell 如何使用`liftIO`和State来打印Monad中的值?

nzrxty8p  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(190)

我尝试使用MonadIO类中的liftIO函数在State monad中打印:

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


所以,原则上,我可以使用liftIOState。问题在哪里?

muk1a3rh

muk1a3rh1#

如果你想做IO,那么IO必须在你的monad Transformer堆栈的底部。下面是通常的mtl修复方法:

facHelper :: (MonadIO m, MonadState Integer m) => Integer -> m ()
-- same definition as before

factorial :: Integer -> IO Integer
factorial n = execStateT (facHelper n) 1

main :: IO ()
main = factorial 6 >>= print

字符串
它使用StateT Integer IO而不是State Integer(即StateT Integer Identity)。
如果你对你的方法出了什么问题的机械细节感到好奇:
1.我要MonadIO (State s)
1.我有type State s = StateT s Identity,所以想要MonadIO (StateT s Identity)
1.我有MonadIO m => MonadIO (StateT s m),更具体地说,我有MonadIO Identity => MonadIO (StateT s Identity),因此需要MonadIO Identity
1.我不(也不能明智地)拥有MonadIO Identity

相关问题