令人信服的scala编译器,Nil具有正确的类型

时间:2014-10-01 08:45:48

标签: scala types functional-programming

所以我在scala中得到了我的List类版本:

sealed trait List[+A] {
  (...)
}

case object Nil extends List[Nothing] 
case class Cons[+A](_head: A, _tail: List[A]) extends List[A]

现在我尝试用我的reverse写下foldLeft,其中包括以下内容:

@annotation.tailrec
def foldLeft[A,B](l: List[A], z: B)(f: (B, A) => B): B = l match {
        case Nil => z
        case Cons(x,xs) => foldLeft(xs,f(z,x))(f)
}

这是有问题的部分:

def revers[A](l:List[A]) : List[A] = foldLeft(l,Nil)((b,a) => Cons(a,b))

给了我类型错误:

[error]  found   : datastructures.Cons[A]
[error]  required: datastructures.Nil.type
[error]         foldLeft(l,Nil)((b,a) => Cons(a,b))

我可以通过不使用Nil来解决这个问题:

def revers[A](l:List[A]) : List[A] = l match {
            case Nil => Nil
            case Cons(x,xs) => foldLeft(xs,Cons(x,Nil))((b,a) => Cons(a,b))
}

但我仍然想知道如何通过这个?

1 个答案:

答案 0 :(得分:3)

您可以指定类型:

scala> def revers[A](l:List[A]) : List[A] = 
               foldLeft(l,Nil:List[A])((b,a) => Cons(a,b))
revers: [A](l: List[A])List[A]

scala> val l:List[Int] = Cons(1,Cons(2,Cons(3,Nil)))
l: List[Int] = Cons(1,Cons(2,Cons(3,Nil)))

scala> revers(l)
res0: List[Int] = Cons(3,Cons(2,Cons(1,Nil)))

Scala的类型推断一次只能处理一个块,因此当你编写foldLeft(l,Nil)时,它希望返回类型为Nil。您传递的函数((b,a)=> Cons(a,b)))的返回类型为Cons [A],从而导致错误。在foldLeft(l,Nil)中指定Nil:List [A]可以防止它。有关更好的说明,请参阅stackoverflow.com/questions/9785655 / ....