如果我有一个具有指定类型类限制的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)
因为Haskell报告基本上是这么说的.它通常被认为有些愚蠢.请参阅GHC用户指南:
所有这些行为都与Haskell 98对数据类型声明的上下文的特殊处理形成对比(Haskell 98报告的第4.2.1节).在Haskell 98中的定义
Run Code Online (Sandbox Code Playgroud)data Eq a => Set' a = MkSet' [a]赋予MkSet'与上面的MkSet相同的类型.但是,不是提供(Eq a)约束,MkSet上的模式匹配'需要(Eq a)约束!GHC忠实地实现了这种行为,虽然它很奇怪.但对于GADT风格的声明,GHC的行为更有用,而且更直观.
不鼓励在常规数据定义上放置上下文,并且可能(将会)在某些时候从语言中删除.要么只将上下文放在函数上(无论如何都是实际需要它),或者使用GADT样式的语法来获得预期的行为.