我最近写的
do
e <- (Left <$> m) <|> (Right <$> n)
more actions
case e of
Left x -> ...
Right y -> ...
Run Code Online (Sandbox Code Playgroud)
这看起来很尴尬。我知道protolude
(和其他一些包)定义
-- Called eitherP in parser combinator libraries
eitherA :: Alternative f => f a -> f b -> f (Either a b)
Run Code Online (Sandbox Code Playgroud)
但即便如此,这一切还是感觉有点手动。有没有一些我没见过的漂亮模式可以收紧它?
现在有几次,我发现自己定义了:
(<?>) :: [a] -> [a] -> [a]
[] <?> ys = ys
xs <?> _ = xs
Run Code Online (Sandbox Code Playgroud)
当然,这是一个关联操作,空列表[]
既是左标识又是右标识。它的功能类似于 Python 的or
.
在我看来,这会是一个很好的(<|>)
,比原来更好的(++)
。选择第一个非空列表感觉更像是我对命名类型类的期望,Alternative
而不是连接列表。诚然,它不太合适MonadPlus
,但我认为为救赎付出的代价很小。我们已经在标准库中拥有(++)
和;(<>)
我们是否需要另一个同义词,或者一个新函数(据我所知)会更有帮助吗?
我起初认为这可能是一个很好的Alternative
例子,但在相关问题的答案ZipList
之后的讨论让我相信了事实并非如此。除了向后兼容性和保持明智之外,当前实例而不是这个新实例还有什么理由呢?MonadPlus
我有一个list
type 的输入[Maybe SomeType]
和一个p
type 的谓词SomeType -> Bool
,我想回答这个问题“谓词是否适用于输入中恰好出现的p
所有s?” SomeType
。
第一部分很简单:(map . fmap) p list
类型为[Maybe Bool]
。
一个重要的信息是我知道这一点length list >= 1
并且all isNothing list == False
两者都成立,因此必须至少有一个Just True
in (map . fmap) p list
。
Bool
但我如何从该列表中取出一首单曲呢?
我认为我可以利用折叠(例如 via foldl
)和Maybe
的MonadPlus
实例,执行如下操作:
allTrueOrNothing :: [Maybe Bool] -> Bool
allTrueOrNothing = fromJust . foldl mplus mzero
Run Code Online (Sandbox Code Playgroud)
但这并不完全正确,因为无论它是什么,mplus
都会返回左操作数,因此即使其输入是 也会返回。Just something
something …