什么是Alternative的"some"和"many"有用?

Pet*_*lák 35 haskell applicative

Alternative,的扩展Applicative,声明empty,<|>这两个功能:

一个或多个:

some :: f a -> f [a]
Run Code Online (Sandbox Code Playgroud)

零或更多:

many :: f a -> f [a]
Run Code Online (Sandbox Code Playgroud)

如果定义,some并且many应该是方程的最小解:

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

many v = some v <|> pure []
Run Code Online (Sandbox Code Playgroud)

我找不到一个实例somemany定义的实例.它们的含义和实际用途是什么?他们一直在使用吗?我只是从这个定义中无法理解他们的目的.

更新:我不是在问什么是什么Alternative,只是什么somemany

J. *_*son 13

我倾向于在Applicative解析器组合库中看到它们.

a :: Parser [String]
a = some (string "hello")
Run Code Online (Sandbox Code Playgroud)

我看到many用于该目的的默认定义Parsingparsers.

我认为Parsec是解析器组合器库的主要示例隐藏了some/ 的使用,many因为它重新定义了类似的东西(<|>).


Wil*_*ess 12

一个基本的例子:用

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 _ = []
Run Code Online (Sandbox Code Playgroud)

我们有

*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 ^^^^^^^^^^^^^^^^^^^^ -}
Run Code Online (Sandbox Code Playgroud)

然后,用

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-> [])
Run Code Online (Sandbox Code Playgroud)

我们得到

*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  ^^^^^^^^^^^^^^^^^^^
-}
Run Code Online (Sandbox Code Playgroud)


Joh*_*ley 9

在STM Applicative中,some意思是:继续尝试,直到它成功至少一次,然后继续尝试直到它失败. many意思是:尽可能多次这样做直到失败.


Lev*_*son 6

Will 提供了一个很好的例子来激励使用这些方法,但您似乎仍然对类型类有误解。

类型类定义列出了该类型类的所有实例所存在的方法的类型签名。它还可能提供这些方法的默认实现,这就是 Alternative 的一些许多方法所发生的情况。

为了成为有效的实例,必须为实例定义所有方法。因此,您发现没有专门为某些许多对象定义实例的实例使用默认实现,并且它们的代码与您的问题中列出的完全相同。

因此,需要明确的是,由于类型类定义给出了默认定义,一些许多确实已定义,并且可以与所有替代实例一起使用。

  • @PetrPudlák我真的很喜欢[这个答案](http://stackoverflow.com/a/7681283/849891)(谢谢,is7s)。 (5认同)
  • 我明白这一切。澄清一下,最基本类型(例如“[]”和“Maybe”)的“some”和“many”的定义只是循环。因此,虽然“some”和“many”的定义对它们来说是有效的,但没有任何意义。 (2认同)