代码之家  ›  专栏  ›  技术社区  ›  user7102951

修改无形状HMap元素后保持类型

  •  1
  • user7102951  · 技术社区  · 8 年前

    我正在尝试使用 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 铸造,以便我可以应用 修改 修改 方法如您所见 Additive Multiplicative 实施 修改 方法正确。我正在努力寻找一种方法来提供证据证明这是真的。。。

    这是上述代码:

    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)
        }
    }
    
    1 回复  |  直到 8 年前
        1
  •  0
  •   user7102951 user7102951    8 年前

    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))
        }
    }