繁体   English   中英

Scala中具有通用可遍历参数的方法的递归调用类型不匹配

[英]Type Mismatch on Recursive Call of Method with Generic Traversable Parameters in Scala

我可以制作一个(愚蠢的) drop wrapper,它接受一些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)
}

为什么在使用drop时会出现Type mismatch情况?

因为xs.drop(1)返回一个T ,而不是您混合到原始xs T with Traversable[E]类型的混合。 recurse ,您将返回未修改的集合,这就是它起作用的原因。

我不确定为什么需要所有这些额外的类型参数(也许我缺少了一些东西),应该这样做:

def dropNR[E](xs: Traversable[E]): Traversable[E] = {
  if (xs.size > 1) dropNR[E](xs.drop(1)) else xs
}

原来我需要使用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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM