Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to append an element to HList

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?

like image 859
Bartosz Jankiewicz Avatar asked Sep 11 '14 22:09

Bartosz Jankiewicz


1 Answers

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.

like image 159
Travis Brown Avatar answered Nov 15 '22 03:11

Travis Brown