Haskell 做符号边缘情况无法进行类型检查

标签 haskell syntax do-notation

我正在尝试了解 do 的规则符号。

这是一些类型检查的代码:

fff :: Maybe Int
fff = do
    _ <- pure $ Just 100
    (+10)
    <$> Just 50

这基本上是 fff = (+10) <$> Just 50 。我假设上面的内容可能不会进行类型检查 - 因为每一行肯定都应该在 Maybe 的上下文中。其中(+10)不是。

为什么要进行上述类型检查?这是上述内容的一个更简单的示例:

fff :: Int -> Maybe Int
fff i = do
    (+10)
    <$> Just i

为什么上面的语法被认为是有效的?这不是“脱糖”吗:

fff i = ((+10) >>= (\i -> fmap (Just i))) i

这确实在 ghci 中给出了类型检查错误。

<小时/>

这是一个按照与上面类似的缩进进行类型检查的示例:

x :: Maybe Int
x = do
  _ <- Just 1
  undefined
  <$> Just 5

(感谢 FP slack 聊天中的 @cvlad 提供上述示例)

最佳答案

这是一种奇怪的交互。

我开始将测试用例简化为此,运行良好。

> x = do succ ; <$> Just 1
> x
Just 2

相比之下,这不会解析:

> y = do { succ ; <$> Just 1 }      
error: parse error

但是,这会解析:

> z = do { succ } <$> Just 1      
> z
Just 2

所以,这就是我认为正在发生的事情。自 token <$>永远无法启动表达式,解析暂时失败。 do解析器规则本质上是最大咀嚼规则:失败时,添加隐式 }然后再试一次。

因此,x上面解析为z 。自 succ是一个单子(monad)值(OP问题中的行(+10))它可以出现在do内。这使得类型检查成功。

引用Haskell Report 2.7

A close brace is also inserted whenever the syntactic category containing the layout list ends; that is, if an illegal lexeme is encountered at a point where a close brace would be legal, a close brace is inserted.

关于Haskell 做符号边缘情况无法进行类型检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60579743/

相关文章:

haskell - 不能从 f x = f₁ y 推导出 f = f₁?

python - Python3 While语法错误

java - : "from.<Integer>"?是什么意思

scala - 如何区分 Scala 中对无参数函数的引用和对该函数的调用?

haskell - Haskell 中 <- 的类型是什么?

Haskell:使用 do 表示法并返回整数值的函数

haskell - 为什么我不能调用函数快速排序 (randomList 10)?

haskell - 用单循环分隔交错元素

haskell - 为什么 Safe Haskell 不支持 Template Haskell?

haskell - <= 和 > 运算符作为函数参数