我可以创建一个(愚蠢的)Traversable
包装器,它接受一些Traversable
类型并使用以下代码返回相同的import scala.collection.TraversableLike
def dropN[E, T <: Traversable[E]]
(xs: T with TraversableLike[E, T], n: Int): T =
{
xs.drop(n)
}
dropN(0 to 3, 1) // returns: Range 1 to 3
类型:
// basically finds the tail
def dropNR[E, T <: Traversable[E]]
(xs: T with TraversableLike[E, T]): T =
{
if (xs.size > 1) dropNR[E,T](xs.drop(1)) else xs
}
但是,如果我尝试使用递归来创建类似的函数:
Type mismatch: expected T with TraversableLike[E, T], actual: T
我收到以下消息:def recurse[E, T <: Traversable[E]]
(xs: T with TraversableLike[E, T]): T =
{
recurse[E,T](xs)
}
。
同时,一个纯粹的传递递归方法没有编译错误(但显然会永远递归)
Type mismatch
为什么我在使用drop时获得service
?
答案 0 :(得分:1)
Because xs.drop(1)
returns a T
, not the mixed in T with Traversable[E]
type you mix in to the original xs
. In recurse
, you're returning the unmodified collection, which is why it works.
I'm not sure why you need all those extra type parameters (perhaps I'm missing something), this should do:
def dropNR[E](xs: Traversable[E]): Traversable[E] = {
if (xs.size > 1) dropNR[E](xs.drop(1)) else xs
}
答案 1 :(得分:0)
原来我需要使用scala> :pa
// Entering paste mode (ctrl-D to finish)
import scala.collection.generic.CanBuildFrom
def dropR[E, D[E] <: Traversable[E]](xs: D[E])
(implicit cbf: CanBuildFrom[D[E], E, D[E]]): D[E] =
{
if (xs.size > 1) dropR[E,D](xs.drop(1).to[D]) else xs.to[D]
}
// Exiting paste mode, now interpreting.
import scala.collection.generic.CanBuildFrom
dropR: [E, D[E] <: Traversable[E]](xs: D[E])(implicit cbf: scala.collection.generic.CanBuildFrom[D[E],E,D[E]])D[E]
scala> val l = List(1,2,3)
l: List[Int] = List(1, 2, 3)
scala> dropR(l)
res0: List[Int] = List(3)
scala> dropR(l.toSeq)
res1: scala.collection.immutable.Seq[Int] = List(3)
scala> dropR(l.toSet)
res2: scala.collection.immutable.Set[Int] = Set(3)
scala> dropR(l.toBuffer)
res3: scala.collection.mutable.Buffer[Int] = ArrayBuffer(3)
:
document.querySelector('#assets').addEventListener('loaded', function (){
// display #startbutton and hide #loadingbutton
document.getElementById('startbutton').style.display = "inline";
document.getElementById('loadingbutton').style.display = "none";
});