我尝试使用HList
来模拟共享同一父级的对象集合。我希望能够:
我能够解决上面的第一点(在下面的方法withIndex
中)。但是,IntelliJ IDEA显示消息Expression of type at.Out doesn't conform to expected type T
的突出显示错误。是否有一个隐含的,我可以添加,以摆脱这个?
对于第二点(下面的方法modify
),我收到编译错误
Error:(31, 13) type mismatch;
found : result.type (with underlying type Value)
required: T
result
为了摆脱asInstanceOf
投射,我是否可以添加隐含的内容,以便我可以应用modify
方法?此外,即使应用modify
方法,我也希望能够获得相同类型的对象。如您所见,Additive
和Multiplicative
正确实施了modify
方法。我正在努力寻找一种方法来提供证据确实是这种情况......
以上引用的代码:
import shapeless._
import shapeless.ops.hlist.At
sealed trait Value {
val value: Double
def modify(newValue: Double): Value
}
case class Additive(value: Double) extends Value {
def modify(newValue: Double): Additive = this.copy(value = value + newValue)
}
case class Multiplicative(value: Double) extends Value {
def modify(newValue: Double): Multiplicative = this.copy(value = value * newValue)
}
case class Collection[L <: HList](values: L)
(implicit
val ev: LUBConstraint[L, Value]) {
def withIndex[T <: Value](index: Nat)(implicit at: At.Aux[L, index.N, T]): T = values(index)
def modify[T <: Value](index: Nat, newValue: Double)(implicit at: At.Aux[L, index.N, T]): T = {
val value = values(index)
val result = value.asInstanceOf[T].modify(newValue)
result
}
}
object App {
def main(args: Array[String]): Unit = {
val val1 = Additive(1.0)
val val2 = Additive(2.0)
val val3 = Multiplicative(3.0)
val coll = Collection(val1 :: val2 :: val3 :: HNil)
val copyVal1: Additive = coll.withIndex(0)
val copyVal2: Additive = coll.withIndex(1)
val copyVal3: Multiplicative = coll.withIndex(2)
coll.modify(0, 1.0)
coll.modify(1, 2.0)
coll.modify(2, 3.0)
}
}
答案 0 :(得分:0)
使用@devkat提供的参考,我设法优化代码以解决问题中陈述的两个问题。在我的实际应用程序中,类结构更嵌套,所以我不得不使用F-bounded多态和自我类型来实现所需的结果。为了完整起见,这是我的代码的最终版本。
import shapeless._
import shapeless.ops.hlist.At
sealed trait Value[+V <: Value[V]] {
this: V =>
val value: Double
def modify(newValue: Double): V
def chainModify(newValues: List[Double]): V = {
newValues.foldLeft(this)((obj, v) => obj.modify(v))
}
}
case class Additive(value: Double) extends Value[Additive] {
def modify(newValue: Double) = this.copy(value = value + newValue)
}
case class Multiplicative(value: Double) extends Value[Multiplicative] {
def modify(newValue: Double) = this.copy(value = value * newValue)
}
trait NonCommutative extends Value[NonCommutative] {
}
case class Divisive(value: Double) extends NonCommutative with Value[Divisive] {
def modify(newValue: Double) = this.copy(value = value / newValue)
}
case class Collection[L <: HList](values: L)
(implicit val ev: LUBConstraint[L, Value[_]]) {
def withIndex[T <: Value[T]](index: Nat)(implicit at: At.Aux[L, index.N, T]): T = values(index)
def modify[T <: Value[T]](index: Nat, newValue: Double)(implicit at: At.Aux[L, index.N, T]): T = {
val value = values(index)
val result = value.modify(newValue)
result
}
}
object App {
def main(args: Array[String]): Unit = {
val val1 = Additive(1.0)
val val2 = Additive(2.0)
val val3 = Multiplicative(3.0)
val val4 = Divisive(4.0)
val coll = Collection(val1 :: val2 :: val3 :: val4 :: HNil)
val copyVal1: Additive = coll.withIndex(0)
val copyVal2: Additive = coll.withIndex(1)
val copyVal3: Multiplicative = coll.withIndex(2)
val copyVal4: Divisive = coll.withIndex(3)
println(copyVal3.chainModify(1.0 :: 2.0 :: 3.0 :: Nil))
println(coll.modify(0, 1.0))
println(coll.modify(1, 2.0))
println(coll.modify(2, 3.0))
println(coll.modify(3, 4.0))
}
}