因使用“==”而引起的(Eq a)没有实例。

时间:2021-05-20 17:05:47

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已经完成了。这是一种更好的标记类型的方法,可以消除编译器的歧义。