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
是什么
答案 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
解析器)的大小必须是有限的,因此对some
和many
使用默认定义将导致无限循环!幸运的是,many
只是经典的正则表达式*
。
该程序包还包含some
的定义,但看起来太像默认定义了,没什么意思。