当函数使用 IO 时,将 fmap 与 may 一起使用



我有一个函数,我想使用它Maybe val。通常我会做func <$> val.但现在假设func使用 IO monad。 func <$> val将返回一个Maybe (IO ())。因此,我必须定义一个新的运算符:

(<$$>) :: Monad m => (a -> m b) -> Maybe a -> m ()
(<$$>) func (Just val) = func val >> return ()
(<$$>) func Nothing    = return ()

所以现在我可以写func <$$> val,但是有没有更好的方法呢?

来自 Data.FoldablemapM_可能是最好的匹配:

Prelude Data.Foldable> :set -XScopedTypeVariables
Prelude Data.Foldable> :t f (a :: Maybe a) -> Data.Foldable.mapM_ f a
f (a :: Maybe a) -> Data.Foldable.mapM_ f a
  :: Monad m => (a -> m b) -> Maybe a -> m ()

如果您想要更专业的类型,还有maybe

Prelude> :t f -> maybe (return ()) (f $)
f -> maybe (return ()) (f $)
  :: Monad m => (a -> m ()) -> Maybe a -> m ()

您的<$$>是从Data.Foldable traverse_的。

单行总是更好吗?以下是undefined纯度的用处:

(<$$>) g x = maybe (return undefined) g x >> return ()

例:

 Prelude> print <$$> (Just 1)
 1
 Prelude> print <$$> Nothing
 Prelude>

如果你的代码中有很多这样的内容,那么使用 MaybeT 转换器可能是值得的:

   (func val -> liftIO . func =<< MaybeT (return val) ) 
        :: (a -> IO b) -> Maybe b -> MaybeT IO b

这不会立即带你比普通IO (Maybe ())更进一步,但它的组成很好。

相关内容

最新更新