什么是Alternative的“some”和“many”有用?

时间:2013-08-07 16:23:03

标签: haskell applicative

AlternativeApplicative的扩展,声明empty<|>以及这两个函数:

  

一个或多个:

some :: f a -> f [a]
     

零或更多:

many :: f a -> f [a]
     

如果已定义,somemany应该是方程式的最小解:

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

many v = some v <|> pure []

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

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

5 个答案:

答案 0 :(得分:13)

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

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

我在many的{​​{3}}中看到了parsers

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

答案 1 :(得分: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 _ = []

我们有

*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  ^^^^^^^^^^^^^^^^^^^
-}

答案 2 :(得分:9)

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

答案 3 :(得分:4)

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

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

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

因此,为了清楚起见,某些很多确实已定义,并且可以与所有替代实例一起使用,这要归功于默认定义给定类型类定义。

答案 4 :(得分:1)

regex-applicative包为a custom many method(正则表达式)类型定义了RE。正则表达式(因此,RE解析器)的大小必须是有限的,因此对somemany使用默认定义将导致无限循环!幸运的是,many只是经典的正则表达式*

该程序包还包含some的定义,但看起来太像默认定义了,没什么意思。