hol*_*ech 5 generics scala typeclass shapeless
我试图创建一个类型类,允许我在任何案例类上增加一个名为"counter"的Int字段,只要该类具有这样的字段.
我试图用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))
Run Code Online (Sandbox Code Playgroud)
它适用于任何具有合适计数器字段的案例类.
我认为这可以使用类型类和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))
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,这不编译.错误是value replace is not a member of generator.Repr.我想这是因为编译器没有任何保证T有一个被调用的字段counter而且它是类型Int.但我怎么能这么说呢?有关Shapeless记录的更好/更多文档吗?或者这是一个完全错误的方式?
你必须隐含地要求一个 Modifier
import shapeless._
import ops.record._
Run Code Online (Sandbox Code Playgroud)
implicit class Incrementer[T, L <: HList](t: T)(
implicit gen: LabelledGeneric.Aux[T, L],
modifier: Modifier.Aux[L, Witness.`'counter`.T, Int, Int, L]
) {
def increment(): T = gen.from(modifier(gen.to(t), _ + 1))
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
314 次 |
| 最近记录: |