update is a rather peculiar artifact in Scala, because it is basically syntactic sugar and does not correspond to any specific method signature. This means that we can be creative and update the arterial polymorphic signature,
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)
In its current form, this leaves the index types on LHS and the value type on RHS is completely unlimited,
scala> i(23, true, 'c') = "foo" res4: (Int, Boolean, Char, String) = (23,true,c,foo)
but we can fix this with some implicit evidence provided by the new tuple support in shapeless 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"