是否在类型类方法中不支持类型类约束?

时间:2016-01-10 22:48:39

标签: haskell

我知道在Haskell中不鼓励数据中的约束。例如,

data Eq b => Bar b = Bar b
没有弃用的扩展名,

是不可能的。我甚至也听说过

data Bar b = Eq b => Bar b

并不常见,甚至气馁。 (这是正确的BTW吗?)

对于类型中的约束,情况是否相同?例如,正在做类似

的事情
class Foo a where
    foo :: Eq b => a -> b

在Haskell也气馁?它是否在真实代码中常见?

1 个答案:

答案 0 :(得分:5)

从使用角度来看,类型类方法与普通的多态函数没有什么不同,普通的多态函数恰好将该类作为其参与者类型变量中一个(or more)的约束。但是签名中可能存在其他类型变量,这些变量需要不受一个类头提供的其他约束。为了能够实现函数,约束(通常)是必要的,因此,对类方法需要约束当然是合理的 - 与data类型的约束不同,这实际上没有用处完全(data的实现只是一些数据布局,它不可能需要来自任何类)的任何方法。

但是,您可以通过在类头中包含额外的约束类型变量来避免此问题:

class (Eq b) => Foo b a where
  foo :: a -> b

有时候,这比你的提案更好,但有时肯定不会更好,例如Foo有一大堆方法,而且只有一方法与b有关。当然,在这种情况下,也可以将foo拆分为其头部中具有b的子类,并将其他方法保留在没有额外约束的类中。但是有两个班而不是一个班也可能不那么好。
因此,如果你发现自己处于一种自然而然的事情,我会认为在类方法中添加约束是完全合法的。

具有此类约束的方法的现有示例是foldMaptraverselift。它不是普遍存在的模式,但绝对不是完全不常见的。

如果考虑类型/数据系列,这看起来有点不同,但即使这样,你也不需要data上的约束,只需处理这个问题的函数数据