以下行
filterM (\x -> Just (x > 0)) [2, 1, 0, -1]
输出
Just [2,1]
和线
filterM (\x -> Just (x > 0)) []
节目
Just []
但我希望它输出Nothing。可以做些什么来可能引入一些适用于所有使用列表的 monad 函数的更改?那么我应该使用其他东西而不是 filterM 还是可以从 Maybe monad 继承一些东西?
您可以使用基于谓词mfilter
将您的转换为空:Just []
mfilter (not . null) . filterM (Just . (>0)) $ []
定义:
flatten :: Maybe [a] -> Maybe [a]
flatten Nothing = Nothing
flatten (Just []) = Nothing
flatten x = x
然后
flatten $ filterM (\x -> Just (x > 0)) []
我不确定您对所有使用列表的 monad 函数的工作是什么意思。没有办法修改列表 monad,这样任何 monad 函数都会自动发生这种情况,因为这需要有效地更改一些其他未知 monad 的绑定。同样,更改所有 monad 函数会有点耗时。
我的建议是使用可组合性。如果内部单子 list 失败,我们想要的是在外部单子 m 中失败。这应该很容易,虽然我不知道该怎么称呼它,所以我将使用failing
.
failing :: MonadPlus m => m [a] -> m [a]
failing = (=<<) $ \l -> case l of
[] -> mzero
_ -> return l
然后failing $ filterM (\x -> Just (x > 0)) []
应该做你想做的事。
我不确定你为什么在这种情况下完全涉及 Maybe (因为你的过滤条件都只使用 Just ),但我假设你有其他原因这样做,或者其他一些有时会失败的条件。