Scala 如何在不实例化成员的情况下处理隐式类型类?
How does scala handle implicit typeclasses without instantiating a member?
我注意到当我试图创建一个 fooSemigroup 的实例时,在第一版中匿名函数创建了一个 fooSemigroup 的实例而不实例化 Foo 的成员,但是当我尝试在没有 SAM 构造的情况下执行此操作时,我需要为 SemigroupOps 创建 foo 的虚拟实例以引入隐式值 ev
.
trait Semigroup[A] {
def combine(x: A, y: A): A
}
case class Foo(v: Int)
// vs 1
implicit val fooSemigroup: Semigroup[Foo] = (x: Foo, y: Foo) => Foo(x.v + y.v)
// vs 2
class fooSemigroup(foo: Foo) extends Semigroup[Foo] {
def combine(x: Foo, y: Foo) = Foo(x.v + y.v)
}
implicit val f: fooSemigroup = Foo(0)
implicit class SemigroupOps[A](x: A) {
def +(y: A)(implicit ev: Semigroup[A]): A = ev.combine(x, y)
}
而不是隐含的class
implicit class fooSemigroup(foo: Foo) extends Semigroup[Foo] {
def combine(x: Foo, y: Foo) = Foo(x.v + y.v)
}
尝试隐式对象
implicit object fooSemigroup extends Semigroup[Foo] {
def combine(x: Foo, y: Foo) = Foo(x.v + y.v)
}
然而,根据 Luis 的建议,implicit val
个实例优先于 implicit object
个实例,否则解析可能会导致 ambiguous implicit values
错误,例如
trait SomeTrait[T] {
def f: T
}
trait ExtendedTrait[T] extends SomeTrait[T] {
def g: T
}
implicit object SomeStringObject extends SomeTrait[String] {
override def f: String = "from object f"
}
implicit object ExtendedStringObject extends ExtendedTrait[String] {
override def f: String = "from extended obj f"
override def g: String = "from extended obj g"
}
implicitly[SomeTrait[String]] // Error: ambiguous implicit values
其中完整的错误状态
Error:(15, 77) ambiguous implicit values:
both object ExtendedStringObject in class A$A7 of type A$A7.this.ExtendedStringObject.type
and object SomeStringObject in class A$A7 of type A$A7.this.SomeStringObject.type
match expected type A$A7.this.SomeTrait[String]
def get$$instance$$res0 = /* ###worksheet### generated $$end$$ */ implicitly[SomeTrait[String]];}
^
我注意到当我试图创建一个 fooSemigroup 的实例时,在第一版中匿名函数创建了一个 fooSemigroup 的实例而不实例化 Foo 的成员,但是当我尝试在没有 SAM 构造的情况下执行此操作时,我需要为 SemigroupOps 创建 foo 的虚拟实例以引入隐式值 ev
.
trait Semigroup[A] {
def combine(x: A, y: A): A
}
case class Foo(v: Int)
// vs 1
implicit val fooSemigroup: Semigroup[Foo] = (x: Foo, y: Foo) => Foo(x.v + y.v)
// vs 2
class fooSemigroup(foo: Foo) extends Semigroup[Foo] {
def combine(x: Foo, y: Foo) = Foo(x.v + y.v)
}
implicit val f: fooSemigroup = Foo(0)
implicit class SemigroupOps[A](x: A) {
def +(y: A)(implicit ev: Semigroup[A]): A = ev.combine(x, y)
}
而不是隐含的class
implicit class fooSemigroup(foo: Foo) extends Semigroup[Foo] {
def combine(x: Foo, y: Foo) = Foo(x.v + y.v)
}
尝试隐式对象
implicit object fooSemigroup extends Semigroup[Foo] {
def combine(x: Foo, y: Foo) = Foo(x.v + y.v)
}
然而,根据 Luis 的建议,implicit val
个实例优先于 implicit object
个实例,否则解析可能会导致 ambiguous implicit values
错误,例如
trait SomeTrait[T] {
def f: T
}
trait ExtendedTrait[T] extends SomeTrait[T] {
def g: T
}
implicit object SomeStringObject extends SomeTrait[String] {
override def f: String = "from object f"
}
implicit object ExtendedStringObject extends ExtendedTrait[String] {
override def f: String = "from extended obj f"
override def g: String = "from extended obj g"
}
implicitly[SomeTrait[String]] // Error: ambiguous implicit values
其中完整的错误状态
Error:(15, 77) ambiguous implicit values:
both object ExtendedStringObject in class A$A7 of type A$A7.this.ExtendedStringObject.type
and object SomeStringObject in class A$A7 of type A$A7.this.SomeStringObject.type
match expected type A$A7.this.SomeTrait[String]
def get$$instance$$res0 = /* ###worksheet### generated $$end$$ */ implicitly[SomeTrait[String]];}
^