I'm experimenting with the following class
import shapeless._
import syntax.std.tuple._
class TestedClass[HL](nodes: HL) {
def addElement[T, OUT](clause: HL => T) = {
new TestedClass[OUT](nodes :+ clause(nodes))
}
}
Obviously this fragment doesn't compile. I don't know how to bind the new tuple nodes :+ clause(nodes)
type to OUT. What I would like to achieve is the following:
scala> val step1 = new TestedClass[(Int)](1)
res1: TestedClass[(Int)]
scala> val step2 = step1.addElement(nodes => 2.0)
res1: TestedClass[(Int, Double)]
Is it possible with Scala?
Yes, it's possible, although not quite so nicely, since Scala doesn't provide syntax for Tuple1
. But the following will work:
import shapeless._, ops.tuple.Prepend
class TestedClass[HL](nodes: HL) {
def addElement[T, OUT](clause: HL => T)
(implicit prepend: Prepend.Aux[HL, Tuple1[T], OUT]) = {
new TestedClass[OUT](prepend(nodes, Tuple1(clause(nodes))))
}
}
And then:
scala> val step1 = new TestedClass[Tuple1[Int]](Tuple1(1))
step1: TestedClass[(Int,)] = TestedClass@4fb78b02
scala> val step2 = step1.addElement(nodes => 2.0)
step2: TestedClass[(Int, Double)] = TestedClass@20406333
The basic trick whenever you want to use an operation from Shapeless is to find the type class you need and require the appropriate instance as an implicit parameter. In this case the Prepend
for tuples is what we want.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With