我有以下来自互联网的代码片段:
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
Run Code Online (Sandbox Code Playgroud)
并不能理解,为什么作者使用liftIO?
的目的是liftIO什么?
它的定义如下:
class (Monad m) => MonadIO m where
-- | Lift a computation from the 'IO' monad.
liftIO :: IO a -> m a
Run Code Online (Sandbox Code Playgroud)
可以举IO a -> [a]吗?它看起来像自然的转变。
IO像操作一样getLine, putStrLn "..."只能在IOmonad内部工作。在任何其他 monad 中使用它们将触发类型错误。
尽管如此,仍有许多 monadsM是根据IO(例如StateT Int IO,显然你的LengthMonad)定义的,因此它们允许将IO动作转换为M-actions,并以这样的方式执行。
但是,我们需要对每个进行转换M:
convertIOintoM1 :: IO a -> M1 a
convertIOintoM2 :: IO a -> M2 a
convertIOintoM3 :: IO a -> M3 a
...
Run Code Online (Sandbox Code Playgroud)
由于这很麻烦,库定义了一个MonadIO具有这种转换功能的类型类,这样上面的所有函数都可以被命名liftIO。
在实践中,liftIO每次想要IO在另一个 monad 中运行操作时都会使用它,前提是此类 monad 允许。
| 归档时间: |
|
| 查看次数: |
1386 次 |
| 最近记录: |