如何将元素追加到HList

时间:2014-09-11 22:58:51

标签: scala shapeless

我正在尝试以下课程

import shapeless._
import syntax.std.tuple._

class TestedClass[HL](nodes: HL) {

    def addElement[T, OUT](clause: HL => T) = {
        new TestedClass[OUT](nodes :+ clause(nodes))
    }
}

显然这个片段没有编译。我不知道如何将新元组nodes :+ clause(nodes)类型绑定到OUT。我想要实现的目标如下:

scala> val step1 = new TestedClass[(Int)](1)
res1: TestedClass[(Int)]

scala> val step2 = step1.addElement(nodes => 2.0)
res1: TestedClass[(Int, Double)]

Scala可以吗?

2 个答案:

答案 0 :(得分:6)

是的,虽然不是很好,但是可能,因为Scala没有为Tuple1提供语法。但以下内容将起作用:

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))))
    }
}

然后:

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

每当您想要使用Shapeless操作时,基本技巧就是找到您需要的类型类,并将相应的实例作为隐式参数。在这种情况下,元组的Prepend就是我们想要的。

答案 1 :(得分:0)

您可以将另一个HList附加到HList:

class TestedClass[A <: HList](nodes: A) {

  def addElement[B, C](clause: A => B) = {
    new TestedClass(nodes :: (clause(nodes) :: HNil))
  }

  // def split[H, T <: HList](l: H :: T) = (l.head, l.tail)
}