来自source:
module Control.Monad.IO.Class (
MonadIO(..)
) where
-- | Monads in which 'IO' computations may be embedded.
-- Any monad built by applying a sequence of monad transformers to the
-- 'IO' monad will be an instance of this class.
--
-- Instances should satisfy the following laws, which state that 'liftIO'
-- is a transformer of monads:
--
-- * @'liftIO' . 'return' = 'return'@
--
-- * @'liftIO' (m >>= f) = 'liftIO' m >>= ('liftIO' . f)@
class (Monad m) => MonadIO m where
-- | Lift a computation from the 'IO' monad.
liftIO :: IO a -> m a
instance MonadIO IO where
liftIO = id
是什么意思
liftIO (m >>= f) = liftIO m >>= (liftIO . f)
特别是(m >>= f)
是什么意思?这里m
是关于类型的函数,f
是关于值的函数。所以这种符号不是无意义的吗?
答案 0 :(得分:1)
正如评论中所述,法律中的m
只是一个值变量,与m
中使用的类型变量m
不同class
}定义。
如果您将法律改写为:
liftIO (act >>= f) = liftIO act >>= (liftIO . f)
相当于:
liftIO $ do x <- act === do x <- liftIO act
f x liftIO (f x)
了解到act
是一个IO动作,然后可能会更清楚发生了什么。表达式act >>= f
表示复合IO操作,在运行时,将运行IO操作act
并将其返回值传递给f
以生成新的IO操作(例如act2
})然后将运行。
法律规定,将此复合IO操作提升到另一个monad会创建一个操作,该操作在运行时等效运行act
的提升版本,将其返回值传递给f
以生成一个新的IO动作,将该动作提升到另一个monad,然后运行它。
作为一个具体示例,getLine >>= print
是IO动作,它读取一行,然后在Haskell字符串语法中打印其值。法律规定你可以将其直接提升到另一个monad:
liftIO $ do x <- getLine
print x
获取执行此操作的操作,或者您可以单独解除IO操作部件:
do x <- liftIO getLine
liftIO (print x)
并获得完全相同的动作。