0

So I've got my version of List class in scala:

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

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

now I'm trying to write reverse in terms of my foldLeft which is the following:

@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)
}

here is the problematic part:

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

that gives me type errors:

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

I've could solve this by not using Nil at all like this:

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))
}

but still I would like to know how can I pass this?

almendar
  • 1,823
  • 13
  • 23

1 Answers1

3

You can specify the type :

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's type inference works one block at a time, so when you write foldLeft(l,Nil), it expects the return type to be Nil. The function you passed ((b,a) => Cons(a,b))) has a return type of Cons[A], leading to the error. Specifying that Nil:List[A] in foldLeft(l, Nil) prevents it. See stackoverflow.com/questions/9785655/… for better explanations.

roterl
  • 1,883
  • 14
  • 24
Marth
  • 23,920
  • 3
  • 60
  • 72
  • Thank you for the answer. Could you explain, why the compiler is complaining? Since Nil is extension of List[Nothing] with List having covariant type constructor I thought that everything should be ok out of the box? If I remember Nothing is a subtype of everything in scala so in particular any 'A' that would be substituted? – almendar Oct 01 '14 at 08:58
  • 1
    Scala's type inference works one block at a time, so when you write `foldLeft(l,Nil)`, it expects the return type to be `Nil`. The function you passed (`(b,a) => Cons(a,b))`) has a return type of `Cons[A]`, leading to the error. Specifying that `Nil:List[A]` in `foldLeft(l, Nil)` prevents it. See http://stackoverflow.com/questions/9785655/why-doesnt-passing-nil-to-foldleft-work for better explanations. – Marth Oct 01 '14 at 09:09
  • Thans again for answering and pointing me in the right direction. – almendar Oct 01 '14 at 09:22