【问题标题】:Issue with Scala recursive types (to build a Hlist)Scala 递归类型的问题(构建 Hlist)
【发布时间】:2016-04-29 23:27:14
【问题描述】:

我正在尝试为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] 吗?

谢谢:)

【问题讨论】:

    标签: scala


    【解决方案1】:

    基本上,编译器无法仅从参数类型确定结果类型R。如果你看,你实际上没有任何代码来确定它。所以编译器选择Nothing

    为了解决这个问题,我相信最小的可能解决方案是使用带有 Appender 类型类的内部类型,而不是像这里那样直接在 HCons 中实现。

    一个比我能写的更好的完整解决方案在这里:http://jnordenberg.blogspot.co.uk/2008/08/hlist-in-scala.html

    【讨论】:

    • 谢谢,确实我当前的版本使用了受此博客启发的东西 :) 但是我还有其他问题,我想我会提出另一个问题 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-03
    • 2021-10-14
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    相关资源
    最近更新 更多