我正在尝试定义一个方法ConcatToList能够转换T~T
或T~T~T
或T~T~T~T
或...的某些对象。
到List[T]
。
我的问题来自于如何定义ConcatToList的类型
def ConcatToList[T](concat: ~[T, ???]) = ...
我应该替换什么?通过?
答案 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响应以获得更好的类型更安全的方式