我正在尝试了解 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
内。这使得类型检查成功。
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/