如果我有一个具有指定类型类限制的ADT,我仍然必须使用此数据类型为每个函数指定相同的类型类。这是什么原因以及如何减少不必要的打字?
E.g:
data Eq a => C a = V a
g :: C a -> Bool
g (V a) = a == a
我得到了:
test.hs:32:13:
No instance for (Eq a)
arising from a use of `=='
In the expression: a == a
In an equation for `g': g (V a) = a == a
Failed, modules loaded: none.
虽然:
g :: Eq a => C a -> Bool
工作正常,但如果我有一长串函数,那么每次指定一个类型类都会成为负担:
f :: Eq a => C a -> Bool
f a = g a
答案 0 :(得分:6)
通常认为对您的ADT设置类型类限制是一个坏主意。相反,请将其关闭并使用(==)
正常编码,无论您身在何处。您的Eq a
依赖关系会渗透您的某些功能,而不是其他功能。
答案 1 :(得分:5)
因为Haskell报告基本上是这么说的。它通常被认为有些愚蠢。 Quoth the GHC User Guide:
所有这些行为都与Haskell 98对数据类型声明的上下文的特殊处理形成对比(Haskell 98报告的第4.2.1节)。在Haskell 98中的定义
data Eq a => Set' a = MkSet' [a]
赋予MkSet'与上面的MkSet相同的类型。但是,不是提供(Eq a)约束,MkSet上的模式匹配'需要(Eq a)约束! GHC忠实地实现了这种行为,虽然它很奇怪。但对于GADT风格的声明,GHC的行为更有用,也更直观。
不鼓励在常规数据定义上放置上下文,并且可能(将会)在某些时候从语言中删除。要么只将上下文放在函数上(无论如何都是需要它),或者使用GADT样式的语法来获得你期望的行为。