4

在阅读了Anthony与样式相关的解析器问题的回复后,我试图说服自己编写单子解析器仍然可以相当紧凑。

所以而不是

reference :: Parser Transc
reference = try $ do string "#{"
                     a <- number
                     char ','
                     b <- number
                     char ','
                     c <- number
                     char '}'
                     return $ Outside (a,b,c)

我们可以简单地拥有:

reference3 :: Parser Transc
reference3 = liftM3 (((Outside .).) .  (,,)) 
             (string "#{" >> number <<! char ',') 
             number
             (char ',' >> number <<! char '}') where 
               (<<!) = liftM2 const

这与 Anthony 提供的应用版本非常相似:

reference2 :: Parser Transc
reference2 = ((Outside .) .) . (,,) 
             <$> (string "#{" *> number2 <* char ',') 
             <*> number2 
             <*> (char ',' *> number2 <* char '}')

...除了在<<!概念上类似于<*定义为liftA2 const含义“序列但丢弃左侧提供的值和使用值”的运算符。

当然 << 对于 来说 是个坏名字,如果我们遵循与and相同的逻辑liftM2 const,它会暗示这<<等价于。flip >>>>==<<

我没有在一个名称下找到“liftM2 const”。这是因为它没有那么有用吗?

4

1 回答 1

10

我不太明白这个问题。每个 monad 也是一个 applicative functor,所以你也可以简单地(*>)在 monadic 表达式中使用。

(在给出这个答案时(2011 年),Applicative它不是 的超类Monad,因此可能有必要添加相应的类实例。)

于 2011-10-24T11:38:51.547 回答