Scala 为什么对于任何给定的类型参数,typeclass只能有一个实现?

Scala 为什么对于任何给定的类型参数,typeclass只能有一个实现?,scala,functional-programming,typeclass,implicit,Scala,Functional Programming,Typeclass,Implicit,我正在读《FP为凡人》一书,书中有以下几行: 对于任何给定的类型参数,typeclass只能有一个实现,这是一个称为typeclass一致性的属性。类型类看起来表面上类似于上一章中的代数接口,但代数不一定是一致的 我不完全理解这一段。假设我们有以下类型类: 特征排序[T]{ def比较(x:T,y:T):整数 } 我可以为Int类型创建两个实现,如下所示: val ord1:Ordering[Int]=新排序[Int]{ 定义比较(x:Int,y:Int):Int= 如果(x>y)1 else

我正在读《FP为凡人》一书,书中有以下几行:

对于任何给定的类型参数,typeclass只能有一个实现,这是一个称为typeclass一致性的属性。类型类看起来表面上类似于上一章中的代数接口,但代数不一定是一致的

我不完全理解这一段。假设我们有以下类型类:

特征排序[T]{
def比较(x:T,y:T):整数
}
我可以为
Int
类型创建两个实现,如下所示:

val ord1:Ordering[Int]=新排序[Int]{
定义比较(x:Int,y:Int):Int=
如果(x>y)1 else如果(x==y)0 else-1
}
val ord2:排序[Int]=新排序[Int]{
定义比较(x:Int,y:Int):Int=
如果(x>y)-1如果(x==y)0其他1
}

当作者说typeclass只能有一个实现时,他们的意思是什么?它不适用于typeclass的实例,因为同一类型可以有多个实例。它适用于什么?还有为什么ADT在这个意义上是不一致的?

类型类的实例被定义为隐式的

implicit val ord1: Ordering[Int] = new Ordering[Int] {
  def compare(x: Int, y: Int): Int =
    if (x > y) 1 else if (x == y) 0 else -1
}

implicit val ord2: Ordering[Int] = new Ordering[Int] {
  def compare(x: Int, y: Int): Int =
    if (x > y) -1 else if (x == y) 0 else 1
}
如果你问
隐式的[Ordering[Int]
,你会

Error: ambiguous implicit values:
 both value ord1 in object App of type => App.Ordering[Int]
 and value ord2 in object App of type => App.Ordering[Int]
 match expected type App.Ordering[Int]

你可以(如你所示),但你“不应该”为什么?因为用于使用类型类的机制通常依赖于某种推理。因此,如果有多个实现,编译器不知道使用哪一个,并且如果必须显式指定所需的实现,那么就失去了TypeClass的一些优势——现在,对于许多TypelCases和许多类型,通常只有一个实例,所以问题不大。然而,我同意有些情况下你会想要一个不同的(比如一个用乘法代替加法的幺半群)。对于这些情况,每种语言都有它的解决方法。Haskell在scala中有
newtypes
,您可以始终将一个优先于另一个(比如在本地范围中定义一个),或者显式地优先于您想要的一个(这与我在之前的评论中所说的有些矛盾,但我相信我们大家都可以同意,最好只在绝对必要的情况下才明确,而在所有其他情况下都默示)@Dmytro Mitin的答案是正确的,因此我不想再添加另一个答案。但我想指出的是,您所问的概念上的差异来自这样一个事实,即接口实现总是由程序员手动选择的。然而,类型类实现是由编译器选择的(通过上述答案中解释的隐式机制)。这就是区别。谢谢,这非常有用。现在我明白了为什么隐式很重要,当我们创建实例并简单地要求它们时。