Подтвердить что ты не робот

Для чего нужны альтернативные "некоторые" и "многие"?

Alternative, расширение Applicative, объявляет empty, <|> и эти две функции:

Один или несколько:

some :: f a -> f [a]

Ноль или больше:

many :: f a -> f [a]

Если определено, some и many должны быть наименьшими решениями уравнений:

some v = (:) <$> v <*> many v

many v = some v <|> pure []

Я не смог найти экземпляр, для которого определены some и many. В чем их смысл и практическое применение? Используются ли они вообще? Я не мог понять их цель только из этого определения.

Обновление: Я не спрашиваю, что такое Alternative, только что some и many

4b9b3361

Ответ 1

Я стараюсь видеть их в библиотеках-комбайнах-анализаторах Applicative.

a :: Parser [String]
a = some (string "hello")

и я вижу many для целей определения по умолчанию Parsing по умолчанию parsers.

Я думаю, что Parsec, являющийся основным примером библиотеки комбинаторов парсеров, скрывает использование some/many, поскольку он переопределяет такие вещи, как (<|>).

Ответ 2

Пример элементарного примера:

import Control.Monad(Functor(..))
import Control.Applicative
import Data.Char

-- char string parser
newtype P a = P { runP :: String -> [(a,String)] }

-- runP (P p) s = p s

instance Functor P where
  -- fmap :: (a -> b) -> f a -> f b
  fmap f (P q) = P (\s -> [ (f y,ys) | (y,ys) <- q s])

instance Applicative P where
  -- pure :: a -> f a
  pure x = P (\s -> [(x,s)])
  -- (<*>) :: f (a -> b) -> f a -> f b
  P p <*> P q = P (\s -> [(x y, ys) | (x,xs) <- p s, (y,ys) <- q xs])

letter = P p where      -- sample parser
  p (x:xs) | isAlpha x = [(x,xs)]
  p _ = []
{-
*Main Data.Char> runP letter "123"
[]
*Main Data.Char> runP letter "a123"
[('a',"123")]
*Main Data.Char> runP ( (:) <$> letter <*> pure []) "a123"
[("a","123")]
*Main Data.Char> runP ( (:) <$> letter <*> ((:)<$>letter <*> pure []) ) "a123"
[]
*Main Data.Char> runP ( (:) <$> letter <*> ((:)<$>letter <*> pure []) ) "ab123"
[("ab","123")]   -- NOT NICE ^^^^^^^^^^^^^^^^^^^^ -}

то

instance Alternative P where
  -- (<|>) :: f a -> f a -> f a
  P p <|> P q = P (\s-> p s ++ q s)
  -- empty :: f a   -- the identity of <|>
  empty = P (\s-> [])

{-
*Main Data.Char> runP (many letter) "ab123"
[("ab","123"),("a","b123"),("","ab123")]
*Main Data.Char> runP (some letter) "ab123"
[("ab","123"),("a","b123")]

*Main Data.Char> runP (optional letter) "ab123"
[(Just 'a',"b123"),(Nothing,"ab123")]
*Main Data.Char> runP (optional letter) "123"
[(Nothing,"123")]

-- and also
Prelude Main Data.Traversable> runP (sequenceA $ replicate 2 letter) "ab123"
[("ab","123")]               --  NICE  ^^^^^^^^^^^^^^^^^^^
-}

Ответ 3

В STM Applicative some будет означать: продолжайте пытаться, пока он не добьется успеха хотя бы один раз, а затем продолжайте делать это до тех пор, пока он не сработает. many означало бы: Делайте это столько раз, сколько сможете до отказа.

Ответ 4

Приведет хороший пример, мотивирующий использование этих методов, но у вас, похоже, все еще есть недоразумение о типах классов.

Определение класса типа перечисляет сигнатуры типов для методов, которые существуют для всех экземпляров класса type. Он также может предоставлять стандартные реализации этих методов, что происходит с альтернативными некоторыми и многими методами.

Чтобы быть допустимыми экземплярами, все методы должны быть определены для экземпляра. Таким образом, те, которые вы обнаружили, которые специально не определяли экземпляры для some или many, использовали стандартные реализации, а код для них точно указан в вашем вопросе.

Итак, просто чтобы быть ясным, некоторые и многие действительно определены и могут использоваться со всеми экземплярами Alternative благодаря определениям по умолчанию заданное с определением класса типа.