I can make a (silly) drop
wrapper which accepts some Traversable
type and returns that same Traversable
type using the following code:
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
However if I try to make a similar function with recursion:
// 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
}
I get the following message: Type mismatch: expected T with TraversableLike[E, T], actual: T
.
Meanwhile a pure pass-through recursive method has no compile errors (but would obviously recurse forever)
def recurse[E, T <: Traversable[E]]
(xs: T with TraversableLike[E, T]): T =
{
recurse[E,T](xs)
}
Why am I getting a Type mismatch
when I use drop?
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
}
Turns out I need to use CanBuildFrom
:
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)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.