为什么 Haskell 函数声明中的拼写错误会导致 GHCi 在之前编译的代码周围抛出错误?

Why does a typo in a Haskell function declaration cause GHCi to throw errors around previously compiling code?

这是一个奇怪的问题。通过 LearnYouaHaskell 学习 Haskell,顺便说一句,很棒的书,我正在实施各种示例。

这在 GHCi 中编译

cylinder :: (RealFloat a) => a -> a -> a
cylinder r h =
    let sideArea = 2 * pi * r * h
    topArea = pi * r ^2
    in  sideArea + 2 * topArea

这在 GHCi 中编译

zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]  
zipWith' _ [] _ = []  
zipWith' _ _ [] = []  
zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys 

如果我故意打错字然后把第二个函数声明成这样

zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]  
zipWith' _ [] _ = []  
zipWith' _ _ [] = []  
zipWith' f (x:xs) (y:ys) = f xs y : zipWith' f xs ys 

然后第一个和第二个函数在编译期间抛出错误 - 至少我认为是这样。

对于代码转储提前抱歉。

它抛出这个我没有更改的关于圆柱函数的以前看不见的错误消息

Prelude> :l functions2.hs
[1 of 1] Compiling Main             ( functions2.hs, interpreted )

functions2.hs:4:26:
    Could not deduce (Integral b0) arising from a use of ‘^’
    from the context (RealFloat a)
      bound by the type signature for
                 cylinder :: RealFloat a => a -> a -> a
      at functions2.hs:1:13-40
    The type variable ‘b0’ is ambiguous
    Note: there are several potential instances:
      instance Integral Int -- Defined in ‘GHC.Real’
      instance Integral Integer -- Defined in ‘GHC.Real’
      instance Integral GHC.Types.Word -- Defined in ‘GHC.Real’
    In the second argument of ‘(*)’, namely ‘r ^ 2’
    In the expression: pi * r ^ 2
    In an equation for ‘topArea’: topArea = pi * r ^ 2

functions2.hs:4:27:
    Could not deduce (Num b0) arising from the literal ‘2’
    from the context (RealFloat a)
      bound by the type signature for
                 cylinder :: RealFloat a => a -> a -> a
      at functions2.hs:1:13-40
    The type variable ‘b0’ is ambiguous
    Note: there are several potential instances:
      instance Num Double -- Defined in ‘GHC.Float’
      instance Num Float -- Defined in ‘GHC.Float’
      instance Integral a => Num (GHC.Real.Ratio a)
        -- Defined in ‘GHC.Real’
      ...plus three others
    In the second argument of ‘(^)’, namely ‘2’
    In the second argument of ‘(*)’, namely ‘r ^ 2’
    In the expression: pi * r ^ 2

以及关于第二个函数中拼写错误的更合理的错误消息

functions2.hs:12:30:
    Couldn't match expected type ‘a’ with actual type ‘[a]’
      ‘a’ is a rigid type variable bound by
          the type signature for
            zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
          at functions2.hs:9:13
    Relevant bindings include
      xs :: [a] (bound at functions2.hs:12:15)
      x :: a (bound at functions2.hs:12:13)
      f :: a -> b -> c (bound at functions2.hs:12:10)
      zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
        (bound at functions2.hs:10:1)
    In the first argument of ‘f’, namely ‘xs’
    In the first argument of ‘(:)’, namely ‘f xs y’
Failed, modules loaded: none. 

为什么?这是一个常见的错误吗?我是否通过破坏第二个来破坏第一个?请指教

这是 GHC bug ticket #9033,于 2014 年 4 月报告并迅速修复。

基本上,每当文件包含几乎 any 类型错误时,GHC 将跳过类型 class 默认步骤,这可能导致文件的其他部分给出虚假的不明确的类型错误。

正如@leftaroundabout 指出的那样,^ 运算符是这种情况的常见触发器,因为它的第二个参数类型与其他类型无关,因此经常需要默认。

工单中列出的 GHC 版本是 7.8.2,而 7.8.3 是在 2104 年 7 月发布的,所以我假设版本是 7.8.3 及更高版本。