繁体   English   中英

使用带有monadic动作的Maybe monad

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM