我有一个函数,我想使用它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.Foldable
的mapM_
可能是最好的匹配:
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 ())
更进一步,但它的组成很好。