-
-
Save sadache/529983 to your computer and use it in GitHub Desktop.
// I really do not like using the syntax that removes points | |
scala> List("one","two") foldLeft ("") (_+_) | |
<console>:6: error: missing parameter type for expanded function ((x$1, x$2) => x$1.$plus(x$2)) | |
List("one","two") foldLeft ("") (_+_) | |
^ | |
// Int ??? | |
scala> List("one","two") foldLeft ("") ((_+_):(String,String) => String) | |
<console>:6: error: type mismatch; | |
found : (String, String) => String | |
required: Int | |
List("one","two") foldLeft ("") ((_+_):(String,String) => String) | |
^ | |
scala> List("one","two").foldLeft ("") (_+_) | |
res2: java.lang.String = onetwo |
there is only one argument to the foldLeft method. Then it return a function that takes the other parameter.
Argh, yes of course.. I give up :-)
Is it a type inference limitation or just a case that the compiler didn't know that the (+) belonged with the foldLeft, since omitting the '.' is only supposed to work with zero or 1 argument methods? If so, then the error message wasn't very helpful as the real "error" was in deciding how to associate the parsed tokens.
Ah, you already commented on my suggestion...
I've been trying to get my head around the type inferer's behaviour around currying too. I got this from a Scheme-friend:
(reduce (lambda (x y)
(cons (if (null? y)
x
(+ x (car y))) y))
'(1 2 3)
'())
=>
(6 5 3)
which I could translate to
List(1, 2, 3).foldRight[List[Int]] (Nil) ((x, l) => if(l.isEmpty) List(x) else l.head + x :: l)
but I felt a bit ashamed for all the dots so as the ML fan boy I am I tried to remove them:
scala> List(1, 2, 3) :\ (Nil : List[Int]) ((x,l) => if(l isEmpty) List(x) else (l head) + x :: l)
<console>:6: error: missing parameter type
List(1, 2, 3) :\ (Nil : List[Int]) ((x,l) => if(l isEmpty) List(x) else (l head) + x :: l)
^
That error makes me want to add the parameter type to l and x in the anonymous function:
scala> List(1, 2, 3) :\ (Nil : List[Int]) ((x : Int, l : List[Int]) => if(l isEmpty) List(x) else (l head) + x :: l)
<console>:6: error: type mismatch;
found : (Int, scala.List[Int]) => scala.collection.immutable.List(in package immutable)[Int]
required: Int
List(1, 2, 3) :\ (Nil : List[Int]) ((x : Int, l : List[Int]) => if(l isEmpty) List(x) else (l head) + x :: l)
^
That obviously didn't work. It seems like the same error you got. In my example I at least mention Int so I didn't think more about it. But in your code Int is never even mention so that makes me think Int is just some kind of hacky last resort somewhere in the type inferer?
Anyway, I tried around a whole lot and finally I noticed that a parenthesis around the first function call did the trick just like in Mirkos example:
scala> (List(1, 2, 3) :\ (List[Int]())) ((x,l) => if(l isEmpty) List(x) else (l head) + x :: l)
res5: List[Int] = List(6, 5, 3)
or maybe this one is the nicest:
scala> (List(1, 2, 3) :\ (Nil : List[Int])) ((x,l) => if(l isEmpty) List(x) else (l head) + x :: l)
res6: List[Int] = List(6, 5, 3)
Here I also typed Nil. The whole thing feels weird but I guess that the type inferer is doing really complex stuff. No simple Hindley–Milner here ;)
Mirko, did the underscores get lost somewhere? I need to do it like this:
scala> (List("one","two") foldLeft ("")) (_+_)
res8: java.lang.String = onetwo
I actually really LOVE point-free currying in ML but I guess the Scala one is somewhat limited and obviously makes the type inferer behave a bit weird sometimes.
I love ML currying, but this is not it and often it gets unpredictable to me. I guess there is a problem of precedence before the type inferencer kicks in. It is very confusing since it is hard to grasp even forgetting about this very case. I don't seem to be getting the mental model and that's why I tent to use it very rarely and only in places where it is clear and obvious.
Hm, actually, I think it doesn't work because you can only omit the
.
, i.e., use the operator notation, if there are 0 or 1 arguments to the function. That would also explain why your type ascription is ignored.