从 [Maybe Bool] 中获取一个 Bool,保证至少包含一个 Just

Enr*_*lis 4 monads haskell functional-programming option-type monadplus

我有一个list type 的输入[Maybe SomeType]和一个ptype 的谓词SomeType -> Bool,我想回答这个问题“谓词是否适用于输入中恰好出现的p所有s?” SomeType

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

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

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

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

allTrueOrNothing :: [Maybe Bool] -> Bool
allTrueOrNothing = fromJust . foldl mplus mzero
Run Code Online (Sandbox Code Playgroud)

但这并不完全正确,因为无论它是什么,mplus都会返回左操作数,因此即使其输入是 也会返回。Just somethingsomethingallTrueOrNothingTrue[Just True, Just False]

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

我发现我可以简单地filter取出Nothings,然后将 sand组合在一起Just,如下所示:

allTrueOrNothing' :: [Maybe Bool] -> Bool
allTrueOrNothing' = all fromJust . filter (fmap not isNothing)
Run Code Online (Sandbox Code Playgroud)

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

Dan*_*ner 11

我会all直接使用:

all . all :: (a -> Bool) -> [Maybe a] -> Bool
Run Code Online (Sandbox Code Playgroud)

如果由于某种原因您必须具有所描述的阶段区别,那么您可以使用专业化and = all id

all and :: [Maybe Bool] -> Bool
Run Code Online (Sandbox Code Playgroud)

  • 我花了一秒钟才意识到这是可行的,因为“[Maybe a]”的形式是“f (ga)”,其中“f”和“g”都是可折叠的。聪明(也许有点太多了;-),但我喜欢)。 (4认同)

chi*_*chi 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
Run Code Online (Sandbox Code Playgroud)

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

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

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

未经测试的代码:

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
Run Code Online (Sandbox Code Playgroud)

  • `newtype And = And (也许是 Bool)`? (2认同)