将函数应用于IO中的值也许

时间:2017-04-15 19:13:46

标签: haskell

我有一个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搜索,但我没有找到任何东西。如果没有,我的实施是好的,还是更简单?

1 个答案:

答案 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的嵌套仿函数的通用包装器具有FunctorApplicative个实例,但它没有{ {1}}实例,因为嵌套两个monad并不一定会产生可以给出合法Monad实例的东西。就是这样,我们通常采用为每个有效的组合量身定制的monad变换器。)