0

Simple question, and sorry if this is a stupid question as I am just beginning in scala. I am getting a type mismatch error that says:

found   : (AnyRef, org.apache.tinkerpop.gremlin.hadoop.structure.io.VertexWritable) => List[Object]
required: ((AnyRef, org.apache.tinkerpop.gremlin.hadoop.structure.io.VertexWritable)) => scala.collection.GenTraversableOnce[?]

But according to this post (I have a Scala List, how can I get a TraversableOnce?), a scala.collection.immutable.List is an Iterable and therefore also a GenTraversableOnce. And yet this error seems to indicate otherwise. And furthermore, when I actually look at the link in the accepted answer of that post, I don't see any reference to the word "traversable".

If the problem has to do with my inner class not being correct, then I have to say this error is extremely uninformative, since requiring that the inner class be of type "?" is obviously a vacuous statement ... Any help in understanding this would be appreciated.

Paul
  • 1,106
  • 1
  • 16
  • 39

1 Answers1

3

Function2[X, Y, Z] is not the same thing as Function1[(X, Y), Z].

Compare these two definitions:

val f: ((Int, Int)) => Int = xy => xy._1 + xy._2
val f: (Int, Int) => Int = (x, y) => x + y

The first could also be written with a pattern-matching, that first decomposes the tuple:

val f: ((Int, Int)) => Int = { case (x, y) => x + y }

This is exactly what the error message asks you to do: provide an unary function that takes a tuple as argument, not a binary function. Note that there is the tupled-method, that does exactly that.

The return types of the functions are mostly irrelevant here, the compiler doesn't get to unify them, because it fails on the types of the inputs.


Also related:

  1. Same story with eta-expansions: Why does my implementation of Haskell snd not compile in Scala
Andrey Tyukin
  • 43,673
  • 4
  • 57
  • 93
  • 2
    @Paul In other words, `List` **is** a `TraversableOnce`, the issue is not that. The issue is that you provided a function that takes **two** parameters, whereas the code expects a function that takes a **single** parameter, which is a tuple of **2** (notice the parentheses in the error message). – Zoltán Sep 10 '18 at 08:44
  • @Zoltán Note that `Paul` will not be notified, because he didn't participate in the comments under this answer. But, yeah, both the question title and the question body are essentially unrelated to the actual problem. My only hope to find it later is through the `arity` tag and the manually added "actually related" links... – Andrey Tyukin Sep 10 '18 at 08:51
  • @Zoltán thank you for your answer. I see your point, though it is a bit surprising that there is not simple conversion from ((Int, Int)) to (Int, Int). Actually this mapping seems to be exactly the canonical projection map; i.e. the map that takes a many-to-one function with a range in a product space and maps it one-to-one with a product of several one-to-one functions. It seems like this would be possible to interpret automatically – Paul Sep 10 '18 at 09:24
  • 1
    @Paul It looks deceptively simple when it comes to `((Int, Int))` vs. `(Int, Int)` distinction. It doesn't look so simple any more as soon as you have overloaded methods with generic parameters `A` that can match both `Int` and `(Int, Int)`, or when you have unification of higher kinded types, which is again more difficult... – Andrey Tyukin Sep 10 '18 at 09:36
  • I see your point. I think I will need to spend some more time hacking on scala before I become completely comfortable with this stuff. In any case, it is working now! – Paul Sep 10 '18 at 09:58
  • 1
    @Paul If this completely answers your question, then you can [mark the question is solved](https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work). Or otherwise please tell us what else you would like to know. – Andrey Tyukin Sep 10 '18 at 10:01