Haskell表达式等价物

时间:2015-01-04 02:39:22

标签: haskell

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

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

看起来效果很好(我使用Parsec包,但我希望这个问题与其功能无关,据我所知<|>是Parsec-定义的中缀运算符)。 parseAparseB都具有Parser Foo monad类型,整个表达式也是如此。

根据我到目前为止所读到的内容,它似乎应该等同于

do return (try parseA <|> parseB)

do return $ try parseA <|> parseB

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

我的其他尝试重写此内容,如

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

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

所以我的问题是,有人可以解释为什么前三个是不同的。我很困惑他们为什么不等同。我错过了什么?


错误(如果这是相关的,虽然我不希望修复我的代码 - 我有一个工作版本,我想了解版本的不同之处):

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)

1 个答案:

答案 0 :(得分:11)

Do Notation Desugaring

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

您可以看到($)不是(=<<)的替代品,但也许您也可以看到它们有些相似。查看它的一种方法是(=<<) - 因此也(>>=) - 是一种应用&#34; monadic函数的函数应用程序&#34;对于某些Monad a -> m b到&#34; monadic值&#34;类型为m的类型对于某些Monad m a类型m,而($)是通常类型的函数应用程序,它将类型a -> b的函数应用于类型a的值。< / p>

Monad Laws

monad laws中的一个就是那个

k >>= return = k

这意味着

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

也可以写成

try parseA <|> parse B

这意味着使用do notation的原始表单也可以这样写。