Haskell注释符号不区分大小写

问题描述 投票:3回答:2

我正在尝试了解do表示法的规则。

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

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

基本上是fff = (+10) <$> Just 50。我认为上述内容可以not类型检查-因为肯定每一行都应该在Maybe的上下文中,而(+10)不在。

为什么要进行上述类型检查?这是上面的简单示例:

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

为什么上述被认为是有效的语法?那不是“去糖”到:

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

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


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

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

(感谢上面示例中的FP闲聊中的@cvlad)

haskell syntax do-notation
2个回答
4
投票

这是一个奇怪的互动。

我开始将测试用例简化为此,可以正常运行。

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

通过比较,这不会解析:

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

但是,此解析:

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

所以,这就是我所想的。由于令牌<$>永远无法启动表达式,因此解析可能会失败。本质上,do解析器规则是最大限制规则:失败时,添加隐式},然后重试。

因此,以上x被解析为z。由于succ是单声道值(OP的问题中的行(+10)),因此它可以出现在do内部。这使类型检查成功。

引用Haskell Report 2.7

在语法类别中也插入一个大括号 包含布局列表结尾;也就是说,如果一个非法的淫秽是 在大括号合法的地方遇到了 插入大括号。


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

为什么上述认为有效的语法?

因为它被解析为

fff i = do {        -- do { A } is just
    (+10) }         --      A
    <$> Just i

相当于

fff i =
    (+10) 
    <$> Just i

因为<$> Just i本身是无效的表达式(因此fff i = ((+10) >>= (\i -> fmap (Just i))) i是不正确的翻译,并且按照@chi答案中引用的规则来界定do块的范围。

实际上是将其类型推断为

fff :: Num b => b -> Maybe b

如果在最后一行的<$>前面添加空格,则第二个示例有效。没有空格,它将再次解析为

inputTest :: FormInput -> IO (Either [String] (Int, Int))
inputTest fi = do {
    allErrors' <- undefined :: IO [String]
    undefined }
    <$> ((liftM2 ) (,) <$> undefined <*> undefined) fi

因为<$> ...本身是无效的表达式。实际上,当我添加显式分隔符时,

inputTest2 :: String -> IO (Either [String] (Int, Int))
inputTest2 fi = do {
    allErrors2 <- undefined :: IO [String] ;
    undefined  }
    <$> ((liftM2 ) (,) <$> undefined <*> undefined) fi

我在TIO上收到完全相同的错误消息(必须在其中使用String而不是您的类型)。

自第一个undefined :: IO [String]起,整个do块都具有某些IO t类型,我们不能在任何内容上映射that

总是添加所有显式分隔符(除了练习良好的缩进样式外),以避免这种奇怪的语法脆弱性。


您的新示例是

x :: Maybe Int
x = do          -- {     this is
  _ <- Just 1   -- ;       how it is
  undefined     -- }         parsed
  <$> Just 5

代码已更改,但答案是相同的。 do之前 <$>Maybe t(由于[C​​0]),我们不能fmap that

再次,使最后一行缩进更多,它将编译,因为Just 1现在将被解析为一个表达式。

© www.soinside.com 2019 - 2024. All rights reserved.