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

And*_*rew 7 haskell typeclass

如果我有一个具有指定类型类限制的ADT,我仍然必须使用此数据类型为每个函数指定相同的类型类.这是什么原因以及如何减少不必要的打字?

例如:

data Eq a => C a = V a
g :: C a -> Bool
g (V a) = a == a
Run Code Online (Sandbox Code Playgroud)

我有:

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.
Run Code Online (Sandbox Code Playgroud)

而:

g :: Eq a => C a -> Bool
Run Code Online (Sandbox Code Playgroud)

工作正常,但如果我有一长串的函数,每次指定一个类型类成为一个负担:

f :: Eq a => C a -> Bool
f a = g a
Run Code Online (Sandbox Code Playgroud)

Dan*_*ons 6

通常认为对您的ADT设置类型类限制是一个坏主意.相反,请将其关闭并正常使用,(==)无论您需要在何处使用.你的Eq a依赖会渗透你的一些功能而不是其他功能.


C. *_*ann 5

因为Haskell报告基本上是这么说的.它通常被认为有些愚蠢.请参阅GHC用户指南:

所有这些行为都与Haskell 98对数据类型声明的上下文的特殊处理形成对比(Haskell 98报告的第4.2.1节).在Haskell 98中的定义

data Eq a => Set' a = MkSet' [a]
Run Code Online (Sandbox Code Playgroud)

赋予MkSet'与上面的MkSet相同的类型.但是,不是提供(Eq a)约束,MkSet上的模式匹配'需要(Eq a)约束!GHC忠实地实现了这种行为,虽然它很奇怪.但对于GADT风格的声明,GHC的行为更有用,而且更直观.

不鼓励在常规数据定义上放置上下文,并且可能(将会)在某些时候从语言中删除.要么只将上下文放在函数上(无论如何都是实际需要它),或者使用GADT样式的语法来获得预期的行为.

  • 从[GHC 7.2.1的发行说明](http://www.haskell.org/ghc/docs/7.2.1/html/users_guide/release-7-2-1.html):_"DatatypeContexts"扩展(默认情况下,它不会出现在下一个Haskell语言标准中)现已关闭,并已弃用.它仍然由`Haskell98`和`Haskell2010`语言启用._ (2认同)