2016-11-02 18 views
1

私はHListを使用して、同じ親を共有するオブジェクトのコレクションをモデル化しようとしています。 シェイプレスHMapの要素を変更した後に型を保持

  • 私が最初に解決することができた
  • 親に定義されたメソッドを使用して、コレクションの特定の要素を変換し、インデックスを使用して、コレクションの

    • アクセス要素:私のことができるようにしたいと思います上のポイント(方法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メソッドを適用しても、同じタイプのオブジェクトを取得できるようにしたいと考えています。表示されるように、AdditiveMultiplicativeは、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

    最初の点については、IntelliJ Ideaの奇妙な点でしょうか? 2番目の点については、この記事を参照してください:http://stackoverflow.com/questions/4313139/how-to-use-scalas-this-typing-abstract-types-etc-to-implement-a-self-type – devkat

    +0

    @devkatの提案では、 'Value''型の' self :: sm01

    答えて

    0

    が@devkatによって提供された参照を使用して、私は洗練するために管理しました問題に記載されている2つの問題を解決するコード。私の実際の仕事のアプリケーションでは、クラス構造がよりネストされているので、目的の結果を得るためにF境界型多態性と自己型を使用しなければなりませんでした。完全性のために、ここに私のコードの最終版があります。

    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)) 
        } 
    } 
    
    関連する問題