Applicative Functor中的条件循环

时间:2014-11-30 09:45:00

标签: parsing haskell applicative

假设Parser x是解析x的解析器。这个解析器可能拥有一个many组合子,可以解析零次或多次出现的事情(当项目解析器失败时停止)。

如果Parser形成一个monad,我可以看到如何实现。如果Parser只是一个Applicative Functor,我无法弄清楚如何做到这一点。似乎没有任何方法可以检查以前的结果并决定下一步该做什么(正是monads添加的概念)。我错过了什么?

3 个答案:

答案 0 :(得分:5)

Alternative类型类提供many组合子:

class Applicative f => Alternative f where
    empty :: f a
    (<|>) :: f a -> f a -> f a
    many  :: f a -> f [a]
    some  :: f a -> f [a]

    some = some'
    many = many'

many' a = some' a <|> pure []
some' a = (:) <$> a <*> many' a
  1. many a组合子的意思是“零或更多”a
  2. some a组合子的意思是“一个或多个”a
  3. 因此:

    1. some a组合器返回一个a后跟many a的列表(即1 + (0 or more))。
    2. many a组合器返回some a或空列表(即(1 or more) | 0)。
    3. many组合器取决于(<|>)运算符,它可以被视为JavaScript等语言的默认运算符。例如,请考虑Alternative的{​​{1}}实例:

      Maybe

      基本上instance Alternative Maybe where empty = Nothing Nothing <|> r = r l <|> _ = l 应该返回左侧值,如果它的真实性。否则它应该返回右侧值。

      (<|>)是一个与Parser类似定义的数据结构(applicative lexer combinators的概念和解析器组合基本相同):

      Maybe

      如果解析失败,则返回data Lexer a = Fail | Ok (Maybe a) (Vec (Lexer a)) 值。否则返回Fail值。由于OkFail <|> pure [],因此pure []组合子知道何时停止并返回空列表。

答案 1 :(得分:3)

只能使用Applicative提供的内容来完成。但是Alternative有一项功能可以为您提供超出Applicative的能力:

(<|>) :: f a -> f a -> f a

此功能可让您“结合”#34;两个Alternativesa没有任何限制。但是怎么样?特定仿函数f固有的东西必须为你提供一种方法。

通常,Alternative需要一些失败或空虚的概念。就像解析器一样,(<|>)意味着&#34;尝试解析它,如果失败,请尝试另外一件事#34;。但这种依赖于以前的价值&#34; 隐藏在实施(<|>)的机制中。它可用于外部接口。

(<|>),可以实现零或一组合:

optional :: Alternative f => f a -> f (Maybe a)
optional v = Just <$> v <|> pure Nothing

somemany的定义相似,但它们需要相互递归的函数。

请注意,Applicative不是Alternative。例如,您无法将Identity仿函数设为Alternative。您将如何实施empty

答案 2 :(得分:1)

manyAlternative(link)的一种类方法,它表明一般应用仿函数并不总是many实现。