我有一个a -> IO (Maybe b)
类型的函数,我想将其应用于IO (Maybe a)
并获取IO (Maybe b)
。我写了一个函数来做到这一点:
ioMaybeApply :: (a -> IO (Maybe b)) -> IO (Maybe a) -> IO (Maybe b)
ioMaybeApply f ioMaybeA = do
maybeA <- ioMaybeA
maybe (return Nothing) f maybeA
有没有标准的Haskell功能呢?我尝试用Hoogle搜索,但我没有找到任何东西。如果没有,我的实施是好的,还是更简单?
答案 0 :(得分:6)
这可以通过MaybeT
monad transformer:
GHCi> import Control.Monad.Trans.Maybe
GHCi> :t \f m -> runMaybeT (MaybeT m >>= MaybeT . f)
\f m -> runMaybeT (MaybeT m >>= MaybeT . f)
:: Monad m => (a1 -> m (Maybe a)) -> m (Maybe a1) -> m (Maybe a)
import Control.Monad.Trans.Maybe
-- Making it look like your definition, for the sake of comparison.
ioMaybeApply :: (a -> IO (Maybe b)) -> IO (Maybe a) -> IO (Maybe b)
ioMaybeApply f ioMaybeA = runMaybeT $ do
a <- MaybeT ioMaybeA
MaybeT (f a)
如果您在多个地方使用此模式,将a -> IO (Maybe b)
功能更改为a -> MaybeT IO b
可能会有所回报 - 然后您可以使用(>>=)
和/或无缝地执行此操作-blocks而不是你的专用功能。另一方面,如果这只是一次性的,你可以合理地认为使用MaybeT
会有点过分;在这种情况下,您的实施完全没问题。
(值得一提的是,虽然有一个名为Compose
的嵌套仿函数的通用包装器具有Functor
和Applicative
个实例,但它没有{ {1}}实例,因为嵌套两个monad并不一定会产生可以给出合法Monad
实例的东西。就是这样,我们通常采用为每个有效的组合量身定制的monad变换器。)