функции '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

например. для разбор (см. раздел "Аппликативный синтаксический анализ на примере" ).