Haskell没有(Eq Digit)实例使用==在表达式中:x == One

Usr*_*Usr 0 binary haskell

data Digit = Zero | One
convBNum :: [Digit] -> Int
convBNum [] = 0
convBNum (x:xs)
  | x == One = 2^length xs + convBNum xs
  | otherwise = convBNum xs
Run Code Online (Sandbox Code Playgroud)

这是将二进制数转换为int的简单函数的代码; 当我编译它时,它给了我这个错误:

no instance for (Eq Digit) arising from a use of == 
In the expression: x == One
Run Code Online (Sandbox Code Playgroud)

如果我理解得很好,也读了其他问题,问题是x不能是任何类型,但我无法理解如何解决这个问题以及如何使用Eq约束.

Fra*_*nky 8

添加一个deriving条款

data Digit = Zero | One deriving (Eq)
Run Code Online (Sandbox Code Playgroud)

或者不使用==,而是使用模式匹配:

convBNum (One:xs) = 2^length xs + convBNum xs
convBNum (_  :xs) =               convBNum xs
Run Code Online (Sandbox Code Playgroud)


sep*_*p2k 6

问题是x不能是任何类型

在你的代码中x有类型Digit,这正是它应该具有的类型.那不是问题.

问题是==运算符是在Eq类类中定义的.这意味着它只能用于那种类型实例的类型,而您的Digit类型不是.为了使一个,你可以提供自己的定义==Digit这样的:

instance Eq Digit where
    Zero == Zero = True
    One == One = True
    _ == _ = False
Run Code Online (Sandbox Code Playgroud)

但是,可以使用关键字自动为自定义数据类型定义某些类型类(如Eq,和)的定义,这通常是可取的.所以你可以写:OrdShowReadderiving

data Digit = Zero | One deriving Eq
Run Code Online (Sandbox Code Playgroud)

这将Eq自动生成上述实例.

请注意,对于您的用例,使用嵌套模式匹配比使用更加惯用==:

convBNum :: [Digit] -> Int
convBNum [] = 0
convBNum (One : xs) = 2^length xs + convBNum xs
convBNum (Zero : xs) = convBNum xs
Run Code Online (Sandbox Code Playgroud)

这种方式你甚至不需要Eq实例,但无论如何都有它是有意义的,因为它Digit是一种真正应该支持的类型==.

在一个不相关的注释中,您可能还应该派生或手动定义一个实例Show,以便您可以print在GHCi中显示数字并显示它们.