Francis Toth
Francis Toth

Reputation: 1685

Scala : Overloaded function with PartialFunction in argument

I've just come across a strange problem while trying to overload a function using a partial function :

class Foo {
  def bar(pf: PartialFunction[String, Int]): Foo = ???
  def bar(zd: Int): Foo = ???
  def zed(pf: PartialFunction[String, Int]): Foo = ???
}

...
new Foo()
  .bar (0)
  .zed { case _ => 1 } // this line is OK
  .bar { case _ => 1 } // This line does not compile

I've pasted this code in the REPL, and got a strange error :

The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: ?
           .bar { case _ => 1 }
                ^

I've checked on the Internet and find different explanations for this error, but not one talking about overloading. As far as I understand, a PartialFunction is expanded to an anonymous function. So in this case, this would result in something like :

object Test {
  new Foo()
    .bar (0)
    .zed { case _ => 1 }
    .bar { (x:String) => x match { case _ => 1 } }
}

But once pasted in the REPL, I get another error :

<console>:17: error: overloaded method value bar with alternatives:
  (zd: Int)Foo <and>
  (pf: PartialFunction[String,Int])Foo
 cannot be applied to (String => Int)
           .bar { (x:String) => x match { case _ => 1 } }
            ^

Which is fine, as there is no signature taking an anonymous function in argument. So what am I missing ? Am I expanding the partial function incorrectly ?

Thank you for any help !

EDIT

I've just found that the problem may come from an ambiguity regarding which method should be called :

object Test {
  new Foo()
    .bar (0)
    .zed { case _ => 1 }
    .bar(PartialFunction({case _ => 1})) // This works
}

Secondly, I've found an interesting similar question here

Upvotes: 2

Views: 299

Answers (2)

som-snytt
som-snytt

Reputation: 39577

As retronym says in the places you linked, it's not a partial function, but a pattern matching anonymous function, which could be either a PartialFunction or a Function depending on what's expected, and the issue is that it can't infer types because typechecking the arg for purposes of overloading happens without an "expected type". The "shape" test lets the function literal work.

scala> object X { def f(i: Int) = ??? ; def f(g: Int => Int) = ??? }
defined object X

scala> X.f { case i => 2 * i }
<console>:13: error: missing parameter type for expanded function
The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: ?
       X.f { case i => 2 * i }
           ^

scala> X.f(i => 2 * i)
scala.NotImplementedError: an implementation is missing
  at scala.Predef$.$qmark$qmark$qmark(Predef.scala:230)
  at X$.f(<console>:11)
  ... 28 elided

scala> X.f({ case i => 2 * i }: Int => Int)
scala.NotImplementedError: an implementation is missing
  at scala.Predef$.$qmark$qmark$qmark(Predef.scala:230)
  at X$.f(<console>:11)
  ... 28 elided

Upvotes: 2

Francis Toth
Francis Toth

Reputation: 1685

Here's the explication of this issue. It seems that the compiler is not able to resolve the type or pattern matching anonymous functions. Simply because their "shape" cannot be resolved. In other words, overloading cannot be used with PartialFunctions.

Upvotes: 0

Related Questions