Haskell <* 和 *> 的应用用法

Haskell Applicative usage of <* and *>

所以我在 Haskell 中创建了一个基本的解析器,我最近了解到,而不是像这样:

sumParser = fmap (\_ a _ b _ -> a + b) ws <*> val <*> plus <*> val <*> eof

我可以使用

之类的东西让它更干净
sumParser = fmap (+) ws *> val <* plus *> val <* eof

显然,我实际上并没有这样做,但这是一个例子。我的问题是,我可以使用 <**> 'skip' 某些解析器 (?) 的 'return' 值,例如 wsval。但是,我真的是 Haskell 的新手,我不确定这是否有意义或如何查找它(我并没有真正从 Hoogle 得到它并环顾四周),但我希望能够一起跳过其中的多个。

我的意思是我想改变这样的东西:

ps = fmap (\_ _ a _ _ _ b _ _ -> a+b) ws <*> p1 <*> val <*> ws <*> p2 <*> ws <*> val <*> ws <*> p3

类似于

ps = fmap (\a b -> a+b) ws *> p1 *> val <* ws * p2 * ws *> val <* ws <* p3

现在无法编译,我不确定如何查找是否可以这样做?

根据我的经验,除了在最简单的情况下混合使用 (*>)(<*) 之外,它变得非常混乱。我倾向于只使用 (<*)(和 (<$))变体。然后我可以从左到右,只决定是否要使用 "next" 项的结果。

在您的示例中,这意味着:

ps = (+) <$ ws <* p1 <*> val <* ws <* p2 <* pw <*> val <* ws <* p3

(此外,假设 ws 可能是空白的缩写:您可能不应该将空白解析器混合到所有内容中,而是编写或多或少自动解析空白的抽象。常见的技术是定义解析器最后自己解析和丢弃空格的组合器,或者首先进行词法分析并让解析器组合器对生成的 list/stream 个标记进行操作。)