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约束.
添加一个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)
问题是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中显示数字并显示它们.