[英]using the Maybe monad with monadic actions
当我有一个Maybe
值时,我想在它上面应用一些Just
或者只是保持一个Nothing
如果它是Nothing
,我有很多方法可以在haskell中实现它。 但是,当我想申请一个monadic动作时,我没有找到简洁的方法。
在这段代码中,为了获得d
我可以使用fmap
。 但是我不能用它来获取c
因为那个需要monadic(在这种情况下是IO
)动作来应用Maybe
的值。
import Control.Applicative
main = do
let x = Just "test.txt"
let d = reverse <$> x -- good
print d
c <- case x of -- verbose
Nothing -> return Nothing
Just y -> Just <$> readFile y
print c
这是一种可行的方式,但它也太冗长了。
c' <- maybe (return Nothing) (\a -> Just <$> readFile a) x
print c'
我确定有一个更短的路,我现在看不到它...
你正在寻找来自Data.Traversable
traverse
- 它是一种应用于不是列表monad的monad的sequence
/ mapM
构造(除了它应用于“traversables”并且适用于比“monads”弱的东西)。 因此,对于您的特定情况,该功能只是:
traverseMaybe f Nothing = return Nothing
traverseMaybe f (Just x) = fmap Just (f x)
但是Data.Traversable
定义了一个更通用的类:
class (Functor t, Foldable t) => Traversable t where
{-# MINIMAL traverse | sequenceA #-}
-- | Map each element of a structure to an action, evaluate these
-- these actions from left to right, and collect the results.
-- actions from left to right, and collect the results. For a
-- version that ignores the results see 'Data.Foldable.traverse_'.
traverse :: Applicative f => (a -> f b) -> t a -> f (t b)
traverse f = sequenceA . fmap f
-- | Evaluate each action in the structure from left to right, and
-- and collect the results. For a version that ignores the results
-- see 'Data.Foldable.sequenceA_'.
sequenceA :: Applicative f => t (f a) -> f (t a)
sequenceA = traverse id
-- | Map each element of a structure to a monadic action, evaluate
-- these actions from left to right, and collect the results. For
-- a version that ignores the results see 'Data.Foldable.mapM_'.
mapM :: Monad m => (a -> m b) -> t a -> m (t b)
mapM = traverse
-- | Evaluate each monadic action in the structure from left to
-- right, and collect the results. For a version that ignores the
-- results see 'Data.Foldable.sequence_'.
sequence :: Monad m => t (m a) -> m (t a)
sequence = sequenceA
这也适用于不是monad的applicative functor,比如ZipLists。
traverse
在这里做你想要的:
c' <- traverse readFile x
print c'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.