web-dev-qa-db-ja.com

Alternativeの「いくつか」と「多く」は何に役立ちますか?

AlternativeApplicativeの拡張、empty<|>、およびこれら2つの関数を宣言します。

1つ以上:

some :: f a -> f [a]

ゼロ以上:

many :: f a -> f [a]

定義されている場合、somemanyは方程式の最小解である必要があります。

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

many v = some v <|> pure []

somemanyが定義されているインスタンスが見つかりませんでした。 それらの意味と実用性は何ですか?それらはまったく使用されていますか?この定義だけでは、その目的を理解することができませんでした。

更新:私はAlternativeとは何かを尋ねているのではなく、somemanyとは何かを尋ねています。

38
Petr Pudlák

私はそれらをApplicativeパーサーコンビネーターライブラリで見る傾向があります。

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

そして、manyParsingの-​​ デフォルトのparsers の定義で使用されているのがわかります。

パーサーコンビネーターライブラリの主要な例であるParsecは、(<|>)のようなものを再定義するため、some/manyの使用を隠していると思います。

14
J. Abrahamson

基本的な例のインスタンス:with

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")]

Prelude Main Data.Traversable> runP (sequenceA $ replicate 2 letter) "ab123"
[("ab","123")]               --  Nice  ^^^^^^^^^^^^^^^^^^^
-}
14
Will Ness

STM Applicativeでは、someは次のことを意味します。少なくとも1回成功するまで試行を続け、その後失敗するまで試行を続けます。 manyは、次のことを意味します。失敗するまで、これをできるだけ多く実行します。

10
John Wiegley

これらのメソッドの使用を動機付ける良い例を提供しますが、型クラスについてはまだ誤解しているようです。

型クラス定義は、型クラスのすべてのインスタンスに存在するメソッドの型シグネチャを一覧表示します。また、これらのメソッドのデフォルトの実装を提供する場合もあります。これは、Alternativeのsomeおよびmanyメソッドで発生していることです。

有効なインスタンスであるためには、すべてのメソッドをインスタンスに対して定義する必要があります。したがって、具体的にsomeまたはmanyのインスタンスを定義しなかったものはdefaultの実装であり、それらのコードは質問にリストされているとおりです。

したがって、明確にするために、一部および多くは実際に定義されており、型クラス定義で指定されたデフォルト定義のおかげで、すべての代替インスタンスで使用できます。

4
Levi Pearson