(Eq a)没有使用'=='

时间:2015-03-20 15:36:52

标签: haskell ghci

在下面的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) == []

我收到以下错误:

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.

但是如果我删除最后一行,那么代码是:

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]]

我可以在交互式提示中执行以下操作,而不会出现错误:

Prelude> :l problem.hs
[1 of 1] Compiling Main             ( problem.hs, interpreted )
Ok, modules loaded: Main.
*Main> test Empty == []
True
*Main>

为什么在== check检查是在源文件中时出现错误,而不是在交互式提示符中出现错误?

2 个答案:

答案 0 :(得分:4)

使value编译所需的是本地类型签名

value = (test Empty :: [[()]]) == []

或者更好的是,使用null

value = null $ test Empty

这是因为test的类型是

test :: EXP a -> [[a]]

value的类型只是Bool。编译器无法准确猜出Eq内部要使用的value实例,它无法从上下文中推断出来。通常,只要您看到== [],就应该将其替换为null函数,因为这样可以避免Eq约束。

它适用于GHCi,因为当您输入(test Empty) == []时,GHCi的扩展默认规则会自动为()类型选择a

答案 1 :(得分:1)

只需使用type:

明确注释它
value = test Empty == ([] :: [[Int]])

[]的类型可以是任何内容:[Int][Float][[Int]]。编译器无法弄清楚,因为即使Exp是多态的。如果你的功能是这样的,你就不必明确注释:

test :: EXP Int -> [[Int]]
test Empty = []
test (Symbol x) = [[x]]

value = test Empty == []

或者即使你准备给它这样的提示:

value :: [[Int]]
value = (test Empty)

value2 = value == []

也就是说,不是使用Int,而是使用()作为@bheklir完成的注释。这是一种更好的标记类型方法,可以消除编译器的歧义。