【问题标题】:Haskell Expression EquivalentsHaskell 表达式等价物
【发布时间】:2015-01-04 02:39:22
【问题描述】:

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

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

这似乎工作得很好(我正在使用Parsec 包,但我希望这个问题与其功能无关,据我所知&lt;|&gt; 是Parsec 定义的中缀运算符)。 parseA 和 parseB 都具有 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)

【问题讨论】:

    标签: haskell


    【解决方案1】:

    做符号去糖

    rules for do notation desugaring 暗示

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

    等价于

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

    ($) 与 (&gt;&gt;=)

    由于(=&lt;&lt;) 是(&gt;&gt;=) 的翻转版本,两者都等价于

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

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

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

    您可以看到($) 不是(=&lt;&lt;) 的替代品,但也许您也可以看到它们有些相似。一种看待它的方法是(=&lt;&lt;)——因此也是(&gt;&gt;=)——是一种函数应用程序,它将a -&gt; m b类型的“一元函数”应用于某些Monadm到@类型的“一元值” 987654340@ 对于某些 Monad m,而 ($) 是一种常用的函数应用程序,它将 a -&gt; b 类型的函数应用于 a 类型的值。

    单子定律

    monad laws 之一是

    k >>= return = k
    

    这意味着

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

    也可以写成

    try parseA <|> parse B
    

    这意味着您使用 do 表示法的原始形式也可以这样写。

    【讨论】:

    • 谢谢,这是我需要了解的提示。我缺少的另一点是
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-07
    • 2011-01-28
    • 2021-06-05
    • 1970-01-01
    • 2010-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多