我从互联网上找到了以下的代码片段:
calculateLength :: LengthMonad Int
calculateLength = do
-- all the IO operations have to be lifted to the IO monad in the monad stack
liftIO $ putStrLn "Please enter a non-empty string: "
s <- liftIO getLine
if null s
then throwError "The string was empty!"
else return $ length s
我不理解,为什么作者使用liftIO
?
liftIO
的目的是什么?
它的定义如下:
class (Monad m) => MonadIO m where
-- | Lift a computation from the 'IO' monad.
liftIO :: IO a -> m a
有没有可能提升 IO a -> [a]
?它看起来像自然变换。
MonadIO m => m a
中运行一个IO a
。例如,一个 Yesod 的Handler
。 - Willem Van OnsemIO a -> [a]
,因为[]
不是MonadIO
的实例。 - Willem Van OnsemLengthMonad
(https://github.com/haskell/mtl/blob/master/Control/Monad/Error.hs#L129)看起来只是一个“monad transformer”。它们旨在将IO
monad包装在EitherT String
中以运行错误(这就是throwError
的目的)。现在,由于这是使用EitherT String IO
工作的,因此我们不能仅在do
块中使用IO a
。我们需要一些东西将它们提升到EitherT String IO
。 - Willem Van OnsemputStrLn "..."
ж— жі•йҖҡиҝҮзұ»еһӢжЈҖжҹҘпјҢдҪҶliftIO $ putStrLn "..."
еҸҜд»ҘгҖӮжӮЁжҳҜеҗҰеңЁиҜўй—®иҝҷжҳҜдёәд»Җд№Ҳпјҹ - chepnerputStrLn
而没有使用liftIO
,你将会得到一个类型错误。 - luqui