5

我有一个 type 的输入list 和一个 type的[Maybe SomeType]谓词,我想回答“谓词是否适用于所有恰好在输入中的 s?”这个问题。.pSomeType -> BoolpSomeType

第一部分很简单:(map . fmap) p list[Maybe Bool].

一个重要信息是我知道length list >= 1并且all isNothing list == False两者都成立,所以必须至少有一个Just Truein (map . fmap) p list

但是我如何Bool从该列表中取出一个单曲呢?

我认为我可以利用折叠(例如 via foldl)和Maybe' 的MonadPlus实例,执行以下操作:

allTrueOrNothing :: [Maybe Bool] -> Bool
allTrueOrNothing = fromJust . foldl mplus mzero

但这并不完全正确,因为如果它不管是什么都mplus返回左操作数,所以即使它的输入是也会返回。Just somethingsomethingallTrueOrNothingTrue[Just True, Just False]

我可以完成任务的最干净/最惯用的方式是什么?

我看到我可以简单地filter取出Nothings,然后将 sand放在一起Just,如下所示:

allTrueOrNothing' :: [Maybe Bool] -> Bool
allTrueOrNothing' = all fromJust . filter (fmap not isNothing)

但我更想知道是否有办法让这些Maybe Bools 表现得像Monoid知道它的Bool内容一样。

4

3 回答 3

11

我会直接使用all

all . all :: (a -> Bool) -> [Maybe a] -> Bool

如果您出于某种原因必须具有您描述的相位区分,那么您可以使用专业化and = all id

all and :: [Maybe Bool] -> Bool
于 2021-09-13T15:37:43.667 回答
5

这似乎有效:

> and . catMaybes $ [Just False, Nothing, Just False]
False
> and . catMaybes $ [Just False, Nothing, Just True]
False
> and . catMaybes $ [Just True, Nothing, Just True]
True

您可以使用catMaybes将列表转换为[Bool],并and得出结论。

(请注意,这将返回Trueall - Nothings 列表,根据您的假设,这是“不可能的”情况。)

如果您绝对想使用幺半群,我想您可以这样做,但这有点麻烦。它将涉及将列表的每个元素包装在 some 中newtype And = And (Maybe Bool),然后定义相关的 monoid 实例,然后进行所有 mconcat操作,最后展开。

未经测试的代码:

newtype And = And (Maybe Bool)

instance Semigroup And where
   And Nothing  <> x            = x
   x            <> And Nothing  = x
   And (Just a) <> And (Just b) = And (Just (a && b))

instance Monoid And where
   mempty = Nothing

allTrueOrNothing :: [Maybe Bool] -> Bool
allTrueOrNothing = fromMaybe False . coerce . mconcat @And . coerce
于 2021-09-13T15:23:48.753 回答
1

最干净的方法是and . catMaybes.

但是您想以某种方式使用知道其Bool内容的 Monoid。&&那是All

> foldMap (fmap All) [Just True,Nothing,Just False]
Just (All {getAll = False})

> foldMap (fmap All) [Just True,Nothing,Just True]
Just (All {getAll = True})
于 2021-09-14T12:37:49.720 回答