some
and many
可以定义为:
some f = (:) <$> f <*> many f
many f = some f <|> pure []
也许有助于了解如何some
会用monadic写成do
syntax:
some f = do
x <- f
xs <- many f
return (x:xs)
So some f
runs f
一次,然后“多次”,并总结结果。many f
runs f
“某些”时间或“替代”仅返回空列表。这个想法是他们都跑f
尽可能频繁地直到“失败”,将结果收集在列表中。不同之处在于some f
立即失败,如果f
失败,同时many f
在这种情况下仍然会成功并“返回”空列表。但这到底是什么means取决于如何<|>
被定义为。
它只对解析有用吗?让我们看看它对 base 中的实例做了什么:Maybe
, []
and STM
.
First Maybe
. Nothing
意味着失败,所以some Nothing
也失败并评估为Nothing
while many Nothing
成功并评估为Just []
. Both some (Just ())
and many (Just ())
永远不会回来,因为Just ()
从未失败!从某种意义上说,他们评估Just (repeat ())
.
对于列表,[]
意味着失败,所以some []
评估为[]
(没有答案)同时many []
评估为[[]]
(只有一个答案,它是空列表)。再次some [()]
and many [()]
不要回来。扩大实例,some [()]
means fmap (():) (many [()])
and many [()]
means some [()] ++ [[]]
,所以你可以说many [()]
是相同的tails (repeat ())
.
For STM
,失败意味着必须重试事务。所以some retry
将重试自身,同时many retry
将简单地返回空列表。some f
and many f
会跑f
重复,直到重试。我不确定这是否有用,但我猜不是。
So, for Maybe
, []
and STM
many
and some
似乎没那么有用。仅当应用程序具有某种导致失败的状态时,它才有用日益可能是在一遍又一遍地运行相同的事情时。对于解析器来说,这是随着每次成功匹配而缩小的输入。