In the following Haskell code:
在以下Haskell代码中:
import Data.List
import Data.Char
data EXP a = Empty | Symbol a
deriving (Show, Eq, Ord)
test :: (Ord a) => EXP a -> [[a]]
test Empty = []
test (Symbol x) = [[x]]
value = (test Empty) == []
I get the following error:
我得到了以下错误:
problem.hs:12:10:
No instance for (Ord a0) arising from a use of `test'
The type variable `a0' is ambiguous
Note: there are several potential instances:
instance Ord a => Ord (EXP a) -- Defined at problem.hs:5:32
instance Integral a => Ord (GHC.Real.Ratio a)
-- Defined in `GHC.Real'
instance Ord GeneralCategory -- Defined in `Data.Char'
...plus 26 others
In the first argument of `(==)', namely `(test Empty)'
In the expression: (test Empty) == []
In an equation for `value': value = (test Empty) == []
problem.hs:12:22:
No instance for (Eq a0) arising from a use of `=='
The type variable `a0' is ambiguous
Note: there are several potential instances:
instance Eq a => Eq (EXP a) -- Defined at problem.hs:5:28
instance Eq a => Eq (GHC.Real.Ratio a) -- Defined in `GHC.Real'
instance Eq GeneralCategory -- Defined in `Data.Char'
...plus 26 others
In the expression: (test Empty) == []
In an equation for `value': value = (test Empty) == []
Failed, modules loaded: none.
But if I remove the last line, so the code is:
但是如果我去掉最后一行,代码是:
import Data.List
import Data.Char
data EXP a = Empty | Symbol a
deriving (Show, Eq, Ord)
test :: (Ord a) => EXP a -> [[a]]
test Empty = []
test (Symbol x) = [[x]]
I can do the following in the interactive prompt, without error:
我可以在交互式提示中执行以下操作,没有错误:
Prelude> :l problem.hs
[1 of 1] Compiling Main ( problem.hs, interpreted )
Ok, modules loaded: Main.
*Main> test Empty == []
True
*Main>
Why do I get an error when the == check is in the source file, but not when it's in the interactive prompt?
当==检查在源文件中时,为什么会出现错误,但在交互提示符中没有?
2 个解决方案
#1
4
What you need to get value
to compile is a local type signature
要编译的值需要一个本地类型签名!
value = (test Empty :: [[()]]) == []
Or better yet, use null
:
或者更好的是,使用null:
value = null $ test Empty
This is because the type of test
is
这是因为测试的类型是。
test :: EXP a -> [[a]]
And the type of value
is just Bool
. The compiler has no way to guess exactly what Eq
instance to use inside of value
, it can't be inferred from the context. In general whenever you see == []
, you should replace this with the null
function since this avoids the Eq
constraint.
而价值的类型就是Bool。编译器无法准确地猜测Eq实例在值内部使用什么,它不能从上下文推断。一般情况下,当您看到==[]时,应该将其替换为空函数,因为这样可以避免Eq约束。
It works in GHCi because when you type in (test Empty) == []
, GHCi's extended defaulting rules will automatically pick ()
for the ambiguous a
type.
它在GHCi中工作,因为当您输入(test Empty) ==[]时,GHCi的扩展默认规则将自动选择()用于模糊类型。
#2
1
Just explicitly annotate it with type:
只是显式地用类型注释它:
value = test Empty == ([] :: [[Int]])
The type of []
can be anything: [Int]
or [Float]
or [[Int]]
. The compiler is not able to figure it out because even Exp
is polymorphic. If your function was like this you wouldn't have to explicitly annotate:
[]的类型可以是任何东西:[Int]或[Float]或[[Int]]。编译器无法计算出来,因为即使是Exp也是多态的。如果您的函数是这样的,您就不必显式地注释:
test :: EXP Int -> [[Int]]
test Empty = []
test (Symbol x) = [[x]]
value = test Empty == []
Or even if you are ready to give it hints like this:
或者即使你已经准备好给它提示:
value :: [[Int]]
value = (test Empty)
value2 = value == []
That said, instead of using Int
, use ()
for annotating as @bheklir has done. That is a better approach of tagging type to remove ambiguity for the compiler.
也就是说,不要使用Int,使用()来注释@bheklir已经完成了。这是一种更好的标记类型的方法,可以消除编译器的歧义。
#1
4
What you need to get value
to compile is a local type signature
要编译的值需要一个本地类型签名!
value = (test Empty :: [[()]]) == []
Or better yet, use null
:
或者更好的是,使用null:
value = null $ test Empty
This is because the type of test
is
这是因为测试的类型是。
test :: EXP a -> [[a]]
And the type of value
is just Bool
. The compiler has no way to guess exactly what Eq
instance to use inside of value
, it can't be inferred from the context. In general whenever you see == []
, you should replace this with the null
function since this avoids the Eq
constraint.
而价值的类型就是Bool。编译器无法准确地猜测Eq实例在值内部使用什么,它不能从上下文推断。一般情况下,当您看到==[]时,应该将其替换为空函数,因为这样可以避免Eq约束。
It works in GHCi because when you type in (test Empty) == []
, GHCi's extended defaulting rules will automatically pick ()
for the ambiguous a
type.
它在GHCi中工作,因为当您输入(test Empty) ==[]时,GHCi的扩展默认规则将自动选择()用于模糊类型。
#2
1
Just explicitly annotate it with type:
只是显式地用类型注释它:
value = test Empty == ([] :: [[Int]])
The type of []
can be anything: [Int]
or [Float]
or [[Int]]
. The compiler is not able to figure it out because even Exp
is polymorphic. If your function was like this you wouldn't have to explicitly annotate:
[]的类型可以是任何东西:[Int]或[Float]或[[Int]]。编译器无法计算出来,因为即使是Exp也是多态的。如果您的函数是这样的,您就不必显式地注释:
test :: EXP Int -> [[Int]]
test Empty = []
test (Symbol x) = [[x]]
value = test Empty == []
Or even if you are ready to give it hints like this:
或者即使你已经准备好给它提示:
value :: [[Int]]
value = (test Empty)
value2 = value == []
That said, instead of using Int
, use ()
for annotating as @bheklir has done. That is a better approach of tagging type to remove ambiguity for the compiler.
也就是说,不要使用Int,使用()来注释@bheklir已经完成了。这是一种更好的标记类型的方法,可以消除编译器的歧义。