typeclass方法中的typeclass约束是不鼓励的吗?

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

data Eq b => Bar b = Bar b

没有弃用的扩展名是不可能的。 我甚至也听到了

data Bar b = Eq b => Bar b

并不常见,甚至不鼓励。 (这是顺利吗?)


类型类中的约束是否也是如此? 例如,正在做类似的事情

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

在Haskell中也不鼓励? 它通常在真实代码中看到吗?


从使用的角度来看,类型类方法与普通的多态函数没有什么不同,它只是将类作为参数类型变量中的一个(或多个)的约束。 但签名中可能还有其他类型的变量需要其他的约束,而这些约束不是由一个类头提供的。 约束(通常)对于您能够实现该函数是必需的,因此,对类方法需要约束是合理的 - 与data类型的约束不同,它实际上根本没有任何用途( data的实现仅仅是一些数据布局,它不可能需要任何类的任何方法†)。

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

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

有时候,这比你的提议更好,但有时候它不会更好,例如Foo有很多方法,而且这些方法只有一个与b有关。 当然,在这种情况下,也可以将foo分解成一个头部为b的子类,并将其他方法留在一个类中,而不受其他约束。 但是有两个班而不是一个班也可能不太好。
因此,如果您发现自己处于这种情况是很自然的事情,那么我认为向类方法添加约束是完全合理的。

具有这种约束的方法的现有示例是foldMaptraverselift 。 这不是一个无处不在的模式,但绝对不是非常罕见的。


†如果考虑类型/数据族,这看起来有点不同,但即使这样,您不需要对data约束,只需要处理这些数据的函数。

链接地址: http://www.djcxy.com/p/43475.html

上一篇: Is a typeclass constraint discouraged in a typeclass method?

下一篇: What is the difference between traits in Rust and typeclasses in Haskell?