元组类型的递归类型

时间:2016-03-19 20:41:06

标签: scala types

我正在尝试定义一个方法ConcatToList能够转换T~TT~T~TT~T~T~T或...的某些对象。 到List[T]

我的问题来自于如何定义ConcatToList的类型

def ConcatToList[T](concat: ~[T, ???]) = ...

我应该替换什么?通过?

2 个答案:

答案 0 :(得分:4)

我会假设这样的代表:

class ~[I, L](val init: I, val last: L)

你实例化如下:

scala> val x: Int ~ Int ~ Int ~ Int = new ~(new ~(new ~(1, 2), 3), 4)
x: ~[~[~[Int,Int],Int],Int] = $tilde@3e6fa38a

您无法使用您建议的形式的签名编写ConcatToList方法,因为无法编写类型约束来准确描述此操作有效的类型。相反,您可以使用类型类:

trait TildeToList[T] {
  type Elem
  def apply(t: T): List[Elem]
}

object TildeToList {
  type Aux[T, E] = TildeToList[T] { type Elem = E }

  implicit def baseTildeToList[E]: Aux[E ~ E, E] = new TildeToList[E ~ E] {
    type Elem = E
    def apply(t: E ~ E): List[E] = List(t.init, t.last)
  }

  implicit def recTildeToList[I, L](implicit ttl: Aux[I, L]): Aux[I ~ L, L] =
    new TildeToList[I ~ L] {
      type Elem = L
      def apply(t: I ~ L): List[L] = ttl(t.init) :+ t.last
    }
}

然后:

def tildeToList[T](t: T)(implicit ttl: TildeToList[T]): List[ttl.Elem] = ttl(t)

其中的工作原理如下:

scala> tildeToList(x)
res0: List[Int] = List(1, 2, 3, 4)

请注意,我们得到的内容是适当的静态类型。

如果您尝试在没有合适形状的值上使用它,您将收到编译时错误:

scala> tildeToList(new ~('a, "a"))
<console>:16: error: could not find implicit value for parameter ttl: TildeToList[~[Symbol,String]]
       tildeToList(new ~('a, "a"))
                  ^

这可能是你想要的。

答案 1 :(得分:0)

下一个代码适用于混合类型列表:

  case class ~~[T, G](l: T, r: G)

  def concat[T, G](v: ~~[T, G]): List[T] = (v.l, v.r) match {
    case (left, right : ~~[T, _]) => left :: concat(right)
    case (left, right: T) => List(left, right)
  }

  println(concat(~~(2, 3)))                   // List(2, 3)
  println(concat(~~(2, ~~(4, 5))))            // List(2, 4, 5)
  println(concat(~~(2, ~~(4, ~~(5, 6)))))     // List(2, 4, 5, 6)
  println(concat(~~(2, ~~("s", 3.3))))        // List(2, s, 3.3)

  // but
  println(concat(~~(~~("s", 3.3), 2)))        // List(~~(s, 3.3), 2)

P.S。我将此作为简单方法的一个例子,但请看Travis响应以获得更好的类型更安全的方式