当我有一个Maybe
值时,如果它是Just
我希望在其上应用某些内容,或者如果它是Nothing
则只保留Nothing
1}},我有很多方法可以在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'
我确定有更短的路,我现在无法看到它......
答案 0 :(得分:6)
您正在寻找来自traverse
的{{1}} - 它是一种Data.Traversable
/ sequence
构造应用于不是列表monad的monad(除了它已应用) “traversables”,适用于比“monads”弱的东西。因此,对于您的特定情况,该功能只是:
mapM
但是traverseMaybe f Nothing = return Nothing
traverseMaybe f (Just x) = fmap Just (f x)
定义了一个更通用的类:
Data.Traversable
这也适用于不是monad的applicative functor,比如ZipLists。
答案 1 :(得分:3)
traverse
在这里做你想做的事:
c' <- traverse readFile x
print c'