【发布时间】:2017-11-24 09:18:54
【问题描述】:
我正在尝试创建一个类型类,它允许我在任何案例类上增加一个名为“counter”的 Int 字段,只要该类具有这样的字段。
我曾尝试用 Shapeless 做到这一点,但我碰壁了(在第一次尝试消化“The Type Astronaut's Guide to Shapeless”、Shapeless 2.0.0 的“功能概述”和 Stack Overflow 上的众多线程之后)。
我想要的是能够做类似的事情
case class MyModel(name:String, counter:Int) {}
val instance = MyModel("Joe", 4)
val incremented = instance.increment()
assert(incremented == MyModel("Joe", 5))
它应该适用于任何具有合适计数器字段的案例类。
我认为使用类型类和 Shapeless 的记录抽象(以及将增量功能作为方法添加的隐式转换)是可能的。裸露的骨头会是这样的:
trait Incrementer[T] {
def inc(t:T): T
}
object Incrementer {
import shapeless._ ; import syntax.singleton._ ; import record._
implicit def getIncrementer[T](implicit generator: LabelledGeneric[T]): Incrementer[T] = new Incrementer[T] {
def inc(t:T) = {
val repr = generator.to(t)
generator.from(repr.replace('counter, repr.get('counter) + 1))
}
}
}
但是,这不会编译。错误是value replace is not a member of generator.Repr。我猜这是因为编译器不能保证 T 有一个名为counter 的字段,并且它的类型为Int。但我怎么能这么说呢?关于 Shapeless 的记录是否有更好/更多的文档?或者这是一个完全错误的方法?
【问题讨论】:
标签: scala generics typeclass shapeless