no instance for (Eq Digit) arising from a use of ==
In the expression: x == One
这是将二进制数转换为int的简单函数的代码;当我编译它时,它给了我这个错误:
config.Routes.MapHttpRoute(
name: "RouteReports",
routeTemplate: "r2/{controller}/{clientId}/{action}",
defaults: new { action = "adherence", controller = "reports" }
);
如果我理解得很好,也读了其他问题,问题是x不能是任何类型,但我无法理解如何解决这个问题以及如何使用Eq约束。
答案 0 :(得分:8)
添加deriving
子句
data Digit = Zero | One deriving (Eq)
或者不要使用==
,而是使用模式匹配:
convBNum (One:xs) = 2^length xs + convBNum xs
convBNum (_ :xs) = convBNum xs
答案 1 :(得分:6)
问题是x不能是任何类型
在您的代码x
中有Digit
类型,这正是它应具有的类型。那不是问题。
问题是==
运算符是在Eq
类型类中定义的。这意味着它只能用于那种类型类实例的类型,而Digit
类型不是。为了使其成为一个,您可以像==
一样为Digit
提供instance Eq Digit where
Zero == Zero = True
One == One = True
_ == _ = False
的定义:
Eq
但是,可以使用{{1}自动为自定义数据类型定义某些类型类(如Ord
,Show
,Read
和deriving
)的定义}关键字,通常更可取。所以你可以写:
data Digit = Zero | One deriving Eq
这将自动生成上述Eq
实例。
请注意,对于您的用例,使用嵌套模式匹配比使用==
更惯用:
convBNum :: [Digit] -> Int
convBNum [] = 0
convBNum (One : xs) = 2^length xs + convBNum xs
convBNum (Zero : xs) = convBNum xs
这样您甚至不需要Eq
实例,但无论如何都要有它,因为Digit
是一种真正应该支持==
的类型。
在不相关的说明中,您可能还应该导出或手动定义Show
的实例,以便您可以print
个数字并在GHCi中显示它们。