如果在数据定义中声明类型,为什么我必须在函数中指定类型类?

时间:2011-08-12 17:00:33

标签: haskell typeclass

如果我有一个具有指定类型类限制的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

2 个答案:

答案 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样式的语法来获得你期望的行为。