哈斯克尔:电梯vs电梯

在什么情况下应该使用liftIO ? 当我使用ErrorT String IOlift函数ErrorT IO动作ErrorTErrorT ,所以liftIO看起来是多余的。

lift总是从“之前”层升起。 如果您需要从第二层提升,则需要lift . lift lift . lift等。

另一方面, liftIO总是从IO层(当存在时总是在堆栈的底部)提升。 所以,如果你有两层以上的monad,你会欣赏liftIO

比较以下lambdaexpression式中的参数types:

 type T = ReaderT Int (WriterT String IO) Bool > :t \x -> (lift x :: T) \x -> (lift x :: T) :: WriterT String IO Bool -> T > :t \x -> (liftIO x :: T) \x -> (liftIO x :: T) :: IO Bool -> T 

liftIO只是IO Monad的一个捷径,无论你使用的是Monad。基本上,liftIO等于使用可变数量的升降机。 起初这可能听起来多余,但是使用liftIO有一个很大的优点:它使得你的IO代码独立于实际的Monad结构,因此无论你最终构build的Monad层的数量如何,都可以重复使用相同的代码(这是相当重要的当写一个monad变压器时)。

另一方面,升降机并不是免费的,就像升降机一样:你使用的Monad变压器必须支持它,例如你所在的Monad必须是MonadIO类的一个实例,但是现在大多数Monad (当然,types检查器会在编译时检查这个:这是Haskell的优势!)。