2

以下行

filterM (\x -> Just (x > 0)) [2, 1, 0, -1] 

输出

Just [2,1]

和线

filterM (\x -> Just (x > 0)) [] 

节目

Just []

但我希望它输出Nothing。可以做些什么来可能引入一些适用于所有使用列表的 monad 函数的更改?那么我应该使用其他东西而不是 filterM 还是可以从 Maybe monad 继承一些东西?

4

3 回答 3

11

您可以使用基于谓词mfilter将您的转换为空:Just []

 mfilter (not . null) . filterM (Just . (>0)) $ []
于 2013-03-13T10:55:10.643 回答
8

定义:

flatten :: Maybe [a] -> Maybe [a]
flatten Nothing   = Nothing
flatten (Just []) = Nothing
flatten x         = x

然后

flatten $ filterM (\x -> Just (x > 0)) []
于 2013-03-13T10:55:04.177 回答
6

我不确定您对所有使用列表的 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 ),但我假设你有其他原因这样做,或者其他一些有时会失败的条件。

于 2013-03-13T10:57:53.760 回答