向类型添加类型类函数
Scala 的类型类实现相当冗长。减少冗长的一种方法是引入所谓的操作类。这些类将在导入变量/值时自动换行以扩展功能。
为了说明这一点,我们首先创建一个简单的类型类:
// The mathematical definition of "Addable" is "Semigroup"
trait Addable[A] {
def add(x: A, y: A): A
}
接下来我们将实现 trait(实例化类型类):
object Instances {
// Instance for Int
// Also called evidence object, meaning that this object saw that Int learned how to be added
implicit object addableInt extends Addable[Int] {
def add(x: Int, y: Int): Int = x + y
}
// Instance for String
implicit object addableString extends Addable[String] {
def add(x: String, y: String): String = x + y
}
}
目前,使用我们的 Addable 实例非常麻烦:
import Instances._
val three = addableInt.add(1,2)
我们宁愿写下写 1.add(2)
。因此,我们将创建一个操作类(也称为“Ops 类”),它将始终包裹实现 Addable
的类型。
object Ops {
implicit class AddableOps[A](self: A)(implicit A: Addable[A]) {
def add(other: A): A = A.add(self, other)
}
}
现在我们可以使用我们的新功能 add
,就好像它是 Int
和 String
的一部分:
object Main {
import Instances._ // import evidence objects into this scope
import Ops._ // import the wrappers
def main(args: Array[String]): Unit = {
println(1.add(5))
println("mag".add("net"))
// println(1.add(3.141)) // Fails because we didn't create an instance for Double
}
}
可以通过 simulacrum 库中的宏自动创建 Ops
类 :
import simulacrum._
@typeclass trait Addable[A] {
@op("|+|") def add(x: A, y: A): A
}