我正在尝试在Scala中实现dropWhile,但是我在调用“f(h)”错误时遇到类型不匹配,该错误表明它实际上找到了它所期望的类型:
def dropWhile[A](l: XList[A])(f: A => Boolean): XList[A] = {
def dropWhile[A](toCheck: XList[A], toKeep: XList[A]) : XList[A] = toCheck match {
case XNil => toKeep
case Cons(h, t) if **f(h)** == false => dropWhile(tail(toCheck), Cons(h, toKeep))
case Cons(_, Cons(t1, t2)) => dropWhile(Cons(t1, t2), toKeep)
}
dropWhile(l, XList[A]())
}
错误消息:
found : h.type (with underlying type A)
[error] required: A
相关代码:
sealed trait XList[+A] {}
case object XNil extends XList[Nothing]
case class Cons[+A](head: A, tail: XList[A]) extends XList[A]
编辑:
这是一种让它编译的方法 - 但获胜的答案更好,并解释了原因。
def dropWhile[A](l: XList[A])(f: A => Boolean): XList[A] = {
@tailrec
def dropWhile[A](toCheck: XList[A], toKeep: XList[A], dropItem: A => Boolean): XList[A] = toCheck match {
case Cons(h, XNil) if !dropItem(h) => Cons(h, toKeep)
case Cons(h, XNil) if dropItem(h) => toKeep
case Cons(h, t) if !dropItem(h) => dropWhile(t, Cons(h, toKeep), dropItem)
case Cons(h, t) if dropItem(h) => dropWhile(t, toKeep, dropItem)
}
dropWhile(l, XList[A](), f)
}
答案 0 :(得分:4)
您在原始'dropWhile'上已经有类型参数A
,其范围为f
。但是,然后在内部def
上引入第二个类型参数,该参数隐藏A
的外部定义并限定XList
的类型。所以问题是A
不是同一类型!如果你删除了阴影类型,它一切正常(为了让你的代码编译而做的其他一些改动):
def dropWhile[A](l: XList[A])(f: A => Boolean): XList[A] = {
def dropWhile(toCheck: XList[A], toKeep: XList[A]) : XList[A] = toCheck match {
case XNil => toKeep
case Cons(h, t) if f(h) == false => dropWhile(t, Cons(h, toKeep))
case Cons(_, Cons(t1, t2)) => dropWhile(Cons(t1, t2), toKeep)
}
dropWhile(l, XNil)
}
答案 1 :(得分:0)
您可以使用foldRight
代替(我将其简化为使用List而不是XList):
scala> def dropWhile[A](l: List[A])(f: A => Boolean): List[A] =
| l.foldRight(List[A]())((h,t) => if (f(h)) t else h :: t)
dropWhile: [A](l: List[A])(f: A => Boolean)List[A]
scala> val l = List(1,2,3,4,5,6,5,4,3,2,1)
l: List[Int] = List(1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1)
scala> l.dropWhile(_ < 4)
res1: List[Int] = List(4, 5, 6, 5, 4, 3, 2, 1)
不回答您的found : h.type (with underlying type A)
问题: - )