Haskell 什么是替代方案';s";“一些”;及;“许多”;对你有用吗?

Haskell 什么是替代方案';s";“一些”;及;“许多”;对你有用吗?,haskell,applicative,some-and-many,alternative-functor,Haskell,Applicative,Some And Many,Alternative Functor,,是Applicative的扩展,声明为空,以及以下两个函数: 一个或多个: some :: f a -> f [a] 零或更多: many :: f a -> f [a] 如果定义,some和many应该是方程的最小解: some v = (:) <$> v <*> many v many v = some v <|> pure [] some v=(:)v多v 多v=一些纯v[] 我找不到定义了some和many的实例它们的意义和实际

,是
Applicative
的扩展,声明
为空
以及以下两个函数:

一个或多个:

some :: f a -> f [a]
零或更多:

many :: f a -> f [a]
如果定义,
some
many
应该是方程的最小解:

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

many v = some v <|> pure []
some v=(:)v多v
多v=一些纯v[]
我找不到定义了
some
many
的实例它们的意义和实际用途是什么?它们是否被使用过?仅仅从这个定义,我无法理解他们的目的


更新:我不是问什么是
备选方案,而是问什么是
一些
许多

我倾向于在
应用程序
解析器组合器库中看到它们

a :: Parser [String]
a = some (string "hello")
我看到在
解析器中有许多用于特定目的的
代码

我认为Parsec是解析器组合器库的主要示例,它隐藏了
一些
/
许多
的使用,因为它重新定义了
()

some
是一个或多个,
many
是根据熟悉的规则反复执行相同计算而收集的0个或多个结果。为了使这一点有意义,某些状态传递(和改变)必须以某种方式减少可能的范围,否则它将无限重复。状态传递和解析是密切相关的


一个简单的例子: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 _ = []

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

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

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


因此,需要明确的是,某些许多确实已定义,并且由于类型类定义提供了默认定义,因此可用于所有的可选实例。

在STM应用程序中,
一些
意味着:继续尝试,直到至少成功一次,然后继续这样做直到失败
many
意味着:尽可能多地执行此操作,直到失败。

包为(正则表达式)类型定义。正则表达式以及因此而产生的
RE
解析器的大小必须是有限的,因此对
some
many
使用默认定义将导致无限循环!幸运的是,
many
只是经典的正则表达式
*


该软件包还包括
some
的定义,但这看起来太像默认定义,没有什么有趣的地方。

虽然这里有一些很好的答案,但是这个问题可能是重复的,它们是它所说的:用于(例如)解析器的多个应用的组合器,在列表中收集结果。我提供了一个简单的例子,其中的定义很容易理解。@WillNess谢谢,我没有考虑解析器。仍然让我困惑的是,为什么它们被包含在
备选方案中,而这些函数对于基本类来说是未定义的。我得到了一个重复的问题。我理解所有这些。为了澄清,对于最基本的类型,例如
[]
部分
的定义可能只是循环。因此,尽管对他们来说,
一些
许多
的定义是有效的,但它没有任何意义。@PetrPudlák我真的很喜欢(谢谢,is7s)。@事实上,这个答案很好。很好的解释!离题,元问题:我注意到您创建了缺少的[haskell alternative]标记。不久前,我也曾想过这样做,甚至编撰了一系列我们可能想添加的问题,但我一直在思考是将MonadPlus和Alternative组合成一个标签(我的本能倾向)还是将它们分开,以及标签的名称(我最初想到的[MonadPlus和Alternative])。我很感激你对这些问题的意见——它可以帮助我最终做出决定:)@duplode我在那里用了“haskell-”,因为“替代方案”本身似乎太模糊、太笼统了。有了“monadplus and-”,从这个角度来看,确实没有必要这么做。至于是否将它们结合在一起,您的列表中是否有许多问题需要
haskell alternative
haskell monadplus
?若并没有,那个么您可以定义后者,并用两者来标记这几个。如果是,您可以将当前标记重命名为
monadplus和alternative
haskell-monadplus和alternative
。或者你的名单太短了(续)@WillNess好主意,[另类函子]听起来不错@意志力:完成!到目前为止,共有64个问题,进展顺利。在39个问题中,其中14个与[另类函子]分享,感觉不那么可靠,尽管可能已经值了入场费。整洁,从来没有想过!
*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  ^^^^^^^^^^^^^^^^^^^
-}