Haskell 异常歧义错误
在以下代码中,当第(4)行编译没有问题时,为什么第(1)行失败: 我知道Haskell 异常歧义错误,haskell,Haskell,在以下代码中,当第(4)行编译没有问题时,为什么第(1)行失败: 我知道DataOrError基本上是或者,这只是为了说明 错误是: prog.hs:8:3: No instance for (Show a0) arising from a use of `print' The type variable `a0' is ambiguous Possible fix: add a type signature that fixes these type variable(
DataOrError
基本上是或者,这只是为了说明
错误是:
prog.hs:8:3:
No instance for (Show a0) arising from a use of `print'
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance (Show a, Show b) => Show (DataOrError a b)
-- Defined at prog.hs:1:50
instance Show Double -- Defined in `GHC.Float'
instance Show Float -- Defined in `GHC.Float'
...plus 24 others
In a stmt of a 'do' block: print (apply (+) x1 x2)
In the expression:
do { print (apply (+) x1 x2);
print (apply (+) x1 e2);
print (apply (+) e1 x2);
print (apply (+) e1 e2) }
In an equation for `main':
main
= do { print (apply (+) x1 x2);
print (apply (+) x1 e2);
print (apply (+) e1 x2);
.... }
where
x1 = Data (2 :: Int)
x2 = Data (3 :: Int)
e1 = Error ("First thing failed")
e2 = Error ("Second thing failed")
您看到一个错误,因为Show(DataOrError a b)
的派生实例如下所示
instance (Show a, Show b) => Show (DataOrError a b) where
...
请注意,a
和b
都必须是Show
实例,才能有其实例。x1
和x2
的类型是DataOrError a Int
,对于e1
和e2
而言,类型是DataOrError String b
。这意味着DataOrError
的其他类型变量不受Show
的约束。可以使用显式类型参数解决此问题:
main :: IO ()
main = do
print (apply (+) x1 x2) -- (1)
print (apply (+) x1 e2) -- (2)
print (apply (+) e1 x2) -- (3)
print (apply (+) e1 e2) -- (4)
where
x1 = Data 2 :: DataOrError String Int
x2 = Data 3 :: DataOrError String Int
e1 = Error "First thing failed" :: DataOrError String Int
e2 = Error "Second thing failed" :: DataOrError String Int
只要类型变量是Show
的一个实例,就可以将任何内容放在那里,包括()
。发生这种情况的唯一原因是编译器试图提供帮助,并推断您未指定的参数比您实际希望的更一般。虽然可以看出这不重要,但编译器不会查看值来确定是否可以打印某些内容,而是查看类型
您在第4行没有看到错误,但在第1行看到错误的原因是因为默认设置。对于第2行和第3行,它可以计算出apply(+)
返回值的完整类型,但在第4行,编译器只知道它必须是numa
。然后,它选择将其默认为Integer
,起初我将其误解为错误,因为我编译时总是将警告视为错误。错误和ideone链接现在包括在内。那么为什么第(4)行编译时没有问题,而第(1)行编译时没有问题?实际上,只使用x1
就可以解决问题,e1
和e2
没有问题地工作。@Clinton为我抛出了一个错误。你使用的是什么版本的GHC?@Clinton噢,没关系,原因是当你有apply(+)x1 x2
时,类型变量仍然未知,当你有xN
和eN
的混合物时,这两个类型变量都具体化了。如果将完整类型签名添加到x1
,则第4行将出现错误。至少我查过了。你查过ideone链接了吗?第4行没有错误。@Clinton我不得不承认有点尴尬,我认为这是一个错误,因为我的构建系统在IDE中标记了它,但这只是一个警告。我只是习惯了把警告当作错误对待。如果在GHC中使用-Wall
进行编译,您将看到变量默认为Integer
,因为编译器通过使用(+)
知道它必须是Num
。如果您有print(apply(++)e1 e2)
它实际上会抛出一个错误,因为++
对该类型变量的约束不足以使其成为默认值。
main :: IO ()
main = do
print (apply (+) x1 x2) -- (1)
print (apply (+) x1 e2) -- (2)
print (apply (+) e1 x2) -- (3)
print (apply (+) e1 e2) -- (4)
where
x1 = Data 2 :: DataOrError String Int
x2 = Data 3 :: DataOrError String Int
e1 = Error "First thing failed" :: DataOrError String Int
e2 = Error "Second thing failed" :: DataOrError String Int