Scala list error

After many Java and some Haskell, I wanted to take a look at Scala. From the code below, I get this error message

type mismatch; found : List[Nothing] => Option[Nothing] required: List[Int] => Option[Nothing]

I don't know what I'm doing wrong:

 object MyFirstScalaObject { def main(args: Array[String]) { lazy val testValues:List[List[Int]] = List((1 to 10).toList, null, List()); println( testFunction(last, testValues)); } def testFunction[I, O](f : I => O, inputs : List[I]): List[(I, O)] = inputs.zip(inputs.map(f)); def last[A](xs:List[A]):Option[A] = xs match { case x::Nil => Some(x); case _::xs => last(xs); case _ => None; } } 

Thanks for any advice.

Greetings

+4
source share
3 answers

due to the way the type input method works in scala, it cannot determine that it should have a parameter of type last , so it must accept the conservative assumption that it is Nothing .

You can explicitly specify types when calling testFunction :

 testFunction[List[Int],Option[Int](last, testValues) 

or you can more fully document the relationship between type parameters in a testFunction , which will give additional information about the type:

 def testFunction[A, I[_], O[_]](f : I[A] => O[A], inputs : List[I[A]]): List[(I[A], O[A])] 

This clearly indicates that I and O are type constructors (kind * → *), now that the input / output types f are more specific, the opponent can correctly conclude that the parameter A for the last function should be Int.

+3
source

A completely redesigned and tested version using the senia idea:

 object MyFirstScalaObject { def main(args: Array[String]) { lazy val testValues = List((1 to 10).toList, null, List()) println(testFunction(testValues)(last)) } def testFunction[I, O](inputs: List[I])(f: I => O): List[(I, O)] = inputs.zip(inputs.map(f)) def last[A](xs: List[A]): Option[A] = xs match { case x :: Nil => Some(x) case _ :: xs => last(xs) case _ => None } } 

Type inference continues from left to right; Information from one parameter list is used in the following parameter list. In this code, when you call testFunction Scala, output I from the first parameter, then it can pass I as the input type of the function f to find out its type (that is, the last argument is applied with A = Int ), then it finally gets the value of O from the return type of the function.

+1
source

I cannot tell you why type inference in scala works this way.

But there is a general way to help the compiler in such cases - parameter sections .

 def testFunction[I, O](inputs : List[I])(f: I => O): List[(I, O)] = inputs.zip(inputs.map(f)) 

Using:

 testFunction(testValues)(last) 

A similar solution is to add the testFunction method to the List class:

 class LastsHelper[T](inputs: List[T]) { def testFunction[O](f: T => O): List[(T, O)] = inputs.zip(inputs.map(f)) } implicit def toLastsHelper[T](inputs: List[T]) = new LastsHelper(inputs) 

You can use methods such as List methods:

 testValues.testFunction(last) 
+1
source

All Articles