Haskell 等价表达式
Haskell Expression Equivalents
我是一个非常新的 Haskell 学习者。我有一个工作表达式:
do x <- try parseA <|> parseB
return x
这似乎完美地工作(我正在使用 Parsec
包,但我希望这个问题与其功能无关,据我所知 <|>
是一个秒差距-定义的中缀运算符)。 parseA
和 parseB
都具有 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 符号的原始形式也可以这样写。
我是一个非常新的 Haskell 学习者。我有一个工作表达式:
do x <- try parseA <|> parseB
return x
这似乎完美地工作(我正在使用 Parsec
包,但我希望这个问题与其功能无关,据我所知 <|>
是一个秒差距-定义的中缀运算符)。 parseA
和 parseB
都具有 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 符号的原始形式也可以这样写。