Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I type an anonymous PartialFunction

Tags:

scala

This works:

scala> List(1, "aa") collect {  case n : Int => n+2 } 
res52: List[Int] = List(3)

And this works beautifully:

scala> var f:PartialFunction[Any, Int] = { case n : Int => n+2 }
f: PartialFunction[Any,Int] = <function1>

scala> var g:PartialFunction[Any, String] = { case n : String => n + " plus two " }
g: PartialFunction[Any,String] = <function1>

scala> List(1, "aa") collect (f orElse g)
res51: List[Any] = List(3, "aa plus two ")

But if I try to do the two together, nope:

scala> List(1, "aa") collect { case n : Int => n+2 } orElse { case n : String => n + " plus two " } 
<console>:8: error: missing parameter type for expanded function
The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: PartialFunction[?,?]
              List(1, "aa") collect { case n : Int => n+2 } orElse { case n : String => n + " plus two " } 

I don't understand exactly why the inference fails, but I can guess. The important question: how do I fix it?

like image 857
Michael Lorton Avatar asked May 01 '14 16:05

Michael Lorton


1 Answers

You need to tell the compiler the argument type of your anonymous PartialFunctions. You can do this directly, by annotating their types:

List(1, "aa") collect ({
  { case n : Int => n+2 }: PartialFunction[Any, _]
} orElse {
  { case n : String => n + " plus two " }: PartialFunction[Any, _]
})

Note that it's necessary to enclose the expression to the right of collect in parentheses.

If you don't like how wordy that is, and you don't mind frustrating whoever tries to understand your code, you could define an identity function on PartialFunctions with an input type of Any:

def pfa[T](f: PartialFunction[Any, T]): PartialFunction[Any, T] = f

List(1, "aa") collect (
  pfa { case n : Int => n+2 }
  orElse pfa { case n : String => n + " plus two " }
)

You could even come up with a suitably weird name and pretend it's a Scala language feature:

def @:[T](f: PartialFunction[Any, T]): PartialFunction[Any, T] = f

scala> @:{case x: Int => x + 3}
res29: PartialFunction[Any,Int] = <function1>
like image 131
Dan Getz Avatar answered Oct 18 '22 05:10

Dan Getz