How to solve type mismatch when compiler finds Serializable instead of the match type?

Rubbic picture Rubbic · Jul 12, 2015 · Viewed 9.1k times · Source

I have have the following parser to parse arithmetic expressions containing Float and RDD :

 import scalaz._
 import Scalaz._

 def term2: Parser[List[\/[Float, RDD[(Int,Array[Float])]]]] = rep(factor2)
 def factor2: Parser[\/[Float, RDD[(Int,Array[Float])]]] = pathxml | num
 def pathxml: Parser[ RDD[(Int,Array[Float])]] = pathIdent ^^ { s => pathToRDD(s)} //pathToRDD is a function that gets the path in string and create an RDD from the file inside that path and pathIdent parse to see whether the input string is a path or not
 def num: Parser[\/[Float, RDD[(Int,Array[Float])]]] = floatingPointNumber ^^ (n => n.left[RDD[(Int,Array[Float])]].toFloat)

Getting the following error:

  [error]  type mismatch;   
  [error]  found   : ParseExp.this.Parser[Serializable]
  [error]  required: ParseExp.this.Parser[scalaz.\/[Float,org.apache.spark.rdd.RDD[(Int, Array[Float])]]]
  [error]   def factor2: Parser[\/[Float, RDD[(Int,Array[Float])]]] = pathxml | num
  [error]                                                                     ^

I am new in Scala and don/t know how I can solve this error

Answer

Travis Brown picture Travis Brown · Jul 12, 2015

Serializable (or similarly Product, or both together) is almost always an indication that you're trying to treat two types as the same when they're not. For example:

scala> if (true) "a" else List(1)
res0: java.io.Serializable = a

The type of a conditional expression is the least upper bound of the types of its two branches—i.e. the most specific type the branches have in common. Here we have a String and a List[Int], which are both instances of AnyRef, but otherwise don't have anything in common besides being Serializable. The fact that they're both Serializable is more specific than the fact that they're both subtypes of AnyRef, so that's the inferred type.

The type of a sequence is inferred similarly:

scala> List("a", "b", "c", 'd)
res1: List[java.io.Serializable] = List(a, b, c, 'd)

In general any time you see Serializable, you should start hunting for something whose type isn't the same as its neighbors or siblings.

In your case pathxml | num is going to be the least upper bound of Parser[RDDThing] and Parser[Float \/ RDDThing], which is again Parser[Serializable]. You should be able to fix this by lifting pathxml into the larger type in your factor2 definition with pathxml.map(_.right) | num.