update
これは主にシンタックス シュガーであり、特定のメソッド シグネチャに対応していないため、Scala ではかなり特殊なアーティファクトです。これは、私たちが創造的になり、アップデートにアリティ ポリモーフィック シグネチャを与えることができることを意味します。
scala> class Indexed { def update[P <: Product](p: P) = p }
defined class Indexed
scala> val i = new Indexed
i: Indexed = Indexed@1ea0e836
scala> i(0) = 1.0
res0: (Int, Double) = (0,1.0)
scala> i(0, 1) = 1.0
res1: (Int, Int, Double) = (0,1,1.0)
scala> i(0, 1, 2) = 1.0
res2: (Int, Int, Int, Double) = (0,1,2,1.0)
scala> i(0, 1, 2, 3) = 1.0
res3: (Int, Int, Int, Int, Double) = (0,1,2,3,1.0)
現状では、これにより、LHS のインデックスの型と RHS の値の型が完全に制約されないままになります。
scala> i(23, true, 'c') = "foo"
res4: (Int, Boolean, Char, String) = (23,true,c,foo)
しかし、形のない2.0.0-SNAPSHOTのタプルの新しいサポートによって提供されるいくつかの暗黙の証拠を使用して、それを修正できます。
scala> import shapeless._
import shapeless._
scala> import syntax.tuple._
import syntax.tuple._
scala> class Indexed {
| def update[P <: Product, I](p: P)
| (implicit
| init: TupleInit.Aux[P, I],
| toList: TupleToList[I, Int],
| last: TupleLast.Aux[P, Double]) = (toList(init(p)), last(p))
| }
defined class Indexed
scala> val i = new Indexed
i: Indexed = Indexed@76ab909a
scala> i(0) = 1.0
res10: (List[Int], Double) = (List(0),1.0)
scala> i(0, 1) = 2.0
res11: (List[Int], Double) = (List(0, 1),2.0)
scala> i(0, 1, 2) = 3.0
res12: (List[Int], Double) = (List(0, 1, 2),3.0)
scala> i(0, 1, 2, 3) = 4.0
res13: (List[Int], Double) = (List(0, 1, 2, 3),4.0)
scala> i(0, 1, 2) = "foo" // Doesn't compile
<console>:22: error: could not find implicit value for parameter
last: shapeless.ops.tuple.TupleLast.Aux[(Int, Int, Int, String),Double]
i(0, 1, 2) = "foo" // Doesn't compile
^
scala> i(23, "foo", true) = 5.0 // Doesn't compile
<console>:22: error: could not find implicit value for parameter
toList: shapeless.ops.tuple.TupleToList[I,Int]
i(23, "foo", true) = 5.0 // Doesn't compile
^