在 Scala 中,我们至少可以使用两种方法来改进现有的或新的类型。假设我们想表达的是,有些东西可以用 Int
来量化。我们可以定义以下特征。
trait Quantifiable{ def quantify: Int }
然后我们可以使用隐式转换来量化,例如字符串和列表。
implicit def string2quant(s: String) = new Quantifiable{
def quantify = s.size
}
implicit def list2quantifiable[A](l: List[A]) = new Quantifiable{
val quantify = l.size
}
导入这些之后,我们可以对字符串和列表调用方法 quantify
。注意,可量化列表存储其长度,因此它避免了在随后调用 quantify
时对列表进行昂贵的遍历。
另一种方法是定义一个“见证者”Quantified[A]
,它声明某种类型的 A
可以被量化。
trait Quantified[A] { def quantify(a: A): Int }
然后,我们在某处为 String
和 List
提供此类型类的实例。
implicit val stringQuantifiable = new Quantified[String] {
def quantify(s: String) = s.size
}
如果我们写一个方法,需要量化它的论点,我们写:
def sumQuantities[A](as: List[A])(implicit ev: Quantified[A]) =
as.map(ev.quantify).sum
或者使用上下文绑定语法:
def sumQuantities[A: Quantified](as: List[A]) =
as.map(implicitly[Quantified[A]].quantify).sum
现在问题来了,我该如何在这两个概念之间做出决定?
到目前为止我所注意到的。
类型类
T
的值来量化事物。我想创建一个类型类 Quantified[A,T]
隐式转换
提出一个(或多个)用例,其中两个概念之间的差异很重要,并解释为什么我更喜欢一个而不是另一个。同时解释这两个概念的本质以及它们之间的关系也是很好的,即使没有例子。