Для чего нужны функции some
и many
в классе Alternative
типов? Документы дают рекурсивное определение, которое я не смог понять.
функции 'some' и 'many' из класса 'Alternative'
Ответ 1
some
и many
можно определить как:
some f = (:) <$> f <*> many f
many f = some f <|> pure []
Возможно, это помогает увидеть, как some
будет написан с монадическим синтаксисом do
:
some f = do
x <- f
xs <- many f
return (x:xs)
Итак some f
запускает f
один раз, затем "много" раз и сохраняет результаты. many f
запускает f
"несколько" раз, или "альтернативно" просто возвращает пустой список. Идея состоит в том, что они оба запускают f
настолько часто, насколько это возможно, пока не "не удастся", собирая результаты в списке. Разница заключается в том, что some f
терпит неудачу, если f
немедленно сбой, а many f
преуспеет и "возвращает" пустой список. Но то, что это все означает, точно зависит от того, как <|>
определено.
Это полезно только для синтаксического анализа? Посмотрим, что он делает для экземпляров в базе: Maybe
, []
и STM
.
Сначала Maybe
. Nothing
означает сбой, поэтому some Nothing
также терпит неудачу и оценивается как Nothing
, а many Nothing
- с ошибкой Just []
. Оба some (Just ())
и many (Just ())
никогда не возвращаются, потому что Just ()
никогда не сработает! В некотором смысле они оценивают значение Just (repeat ())
.
Для списков []
означает сбой, поэтому some []
оценивает []
(нет ответов), а many []
оценивается как [[]]
(есть один ответ, и это пустой список). Опять some [()]
и many [()]
не возвращаются. Расширение экземпляров some [()]
означает fmap (():) (many [()])
и many [()]
означает some [()] ++ [[]]
, поэтому вы можете сказать, что many [()]
совпадает с tails (repeat ())
.
Для STM
отказ означает, что транзакция должна быть повторена. Таким образом, some retry
повторит попытку, а many retry
просто вернет пустой список. some f
и many f
будут запускать f
несколько раз, пока он не повторит попытку. Я не уверен, что это полезная вещь, но я предполагаю, что это не так.
Итак, для Maybe
, []
и STM
many
и some
, похоже, не так полезны. Это полезно только в том случае, если в аппликативном состоянии есть какое-то состояние, которое делает сбой более вероятным при повторении одного и того же предмета снова и снова. Для парсеров это вход, который уменьшается с каждым успешным совпадением.
Ответ 2
например. для разбор (см. раздел "Аппликативный синтаксический анализ на примере" ).