我正在尝试为a small Scala utility lib构建异构列表递归类型。 我有问题要连接2 Hlist并保持一致的类型。
trait HList {
def ::[U](v: U): HList
}
class HNil extends HList {
override def ::[T](v: T) = HCons(v, this)
}
case object HNil extends HNil
case class HCons[T, U <: HList](head: T, tail: U) extends HList {
def ++[V <: HList, R <: HList](l2: V): HCons[T, R] = {
def append(l1: HCons[T, _], l2: V): HCons[T, _] = {
l1.tail match {
case HNil => HCons(l1.head, l2)
case h: HCons[T, U] => l1.head :: append(h, l2)
}
}
append(this, l2) match {
case h: HCons[T,R] => h
}
}
}
这是有效的,所以在运行时类型没问题:
val sum = (2.0 :: "hi" :: HNil) ++ (1 :: HNil)
sum shouldBe 2.0 :: "hi" :: 1 :: HNil
sum shouldBe a[HCons[_, HCons[_, HCons[_, HNil]]]]
但以下代码未编译:
val sum = (2.0 :: "hi" :: HNil) ++ (1 :: HNil)
sum.tail.head
:value head is not a member of Nothing
你知道如何告诉计算机选择sum.tail的正确类型,即HCons [Int,HNil]吗?
谢谢:)
答案 0 :(得分:1)
基本上,编译器不能仅从参数类型确定结果类型R
。如果你看,你实际上没有任何代码可以确定它。所以编译器选择Nothing
。
为了解决这个问题,我认为最小的解决方案是使用带有Appender
类型类的内部类型,而不是直接在HCons
内部实现,就像你在这里一样。
写出比我更好的完整解决方案:http://jnordenberg.blogspot.co.uk/2008/08/hlist-in-scala.html