Haskell 等价表达式

Haskell Expression Equivalents

我是一个非常新的 Haskell 学习者。我有一个工作表达式:

do x <- try parseA <|> parseB
   return x

这似乎完美地工作(我正在使用 Parsec 包,但我希望这个问题与其功能无关,据我所知 <|> 是一个秒差距-定义的中缀运算符)。 parseAparseB 都具有 Parser Foo monad 类型,整个表达式也是如此。

根据我目前阅读的内容,这似乎应该等同于

do return (try parseA <|> parseB)

do return $ try parseA <|> parseB

但是后者都没有编译,他们抱怨类型不匹配(下面的错误)。

我的另一个重写尝试,如

(try parseA <|> parse B) >>= return

似乎有效。但是如果我也误解了这一点,请说出来。

所以我的问题是,谁能解释一下为什么前三个不同。我很困惑为什么它们不相等。我错过了什么?


错误(如果这是相关的,虽然我现在不看 'fix' 我的代码 - 我有一个工作版本,我想了解这些版本有何不同):

do return (try parseA <|> parseB)

给予

parse.hs:76:11:
    Couldn't match expected type ‘Foo’
                with actual type ‘Text.Parsec.Prim.ParsecT
                                    [Char] () Data.Functor.Identity.Identity Foo’

do return $ try parseA <|> parseB

给予

parse.hs:76:3:
    Couldn't match type ‘Text.Parsec.Prim.ParsecT
                           [Char] () Data.Functor.Identity.Identity Foo’
                  with ‘Foo’
    Expected type: Parser Foo
      Actual type: Text.Parsec.Prim.ParsecT
                     String
                     ()
                     Data.Functor.Identity.Identity
                     (Text.Parsec.Prim.ParsecT
                        [Char] () Data.Functor.Identity.Identity Foo)

进行符号脱糖

rules for do notation desugaring 意味着

do x <- try parseA <|> parseB
   return x

等同于

(try parseA <|> parse B) >>= return

($)(>>=)

由于 (=<<)(>>=) 的翻转版本,两者都等同于

return =<< (try parseA <|> parse B)

这意味着你的正确版本和return $ try parseA <|> parse B之间的唯一区别是(=<<)($)之间的区别,它们的类型是:

($)   :: (a -> b)   -> a   -> b
(=<<) :: (a -> m b) -> m a -> m b

您可以看出 ($) 不是 (=<<) 的替代品,但也许您也可以看出它们有些相似。一种看待它的方式是 (=<<) —— 因此也是 (>>=) —— 是一种函数应用程序,它为某些 Monad [=29= 应用 a -> m b 类型的 "monadic functions" ] 到 m a 类型的 "monadic values" 对于某些 Monad m,而 ($) 是通常的函数应用程序,它将类型 a -> b 的函数应用于类型的值a.

单子定律

其中一个monad laws

k >>= return = k

这意味着

(try parseA <|> parse B) >>= return

也可以写成

try parseA <|> parse B

这意味着您使用 do 符号的原始形式也可以这样写。