Friday, February 19, 2010

=>? type alias for PartialFunction

A big thanks to Ben Jackman for this tip.

His tip cleans up the examples in post Chaining Partial Functions with orElse
The secret is to define the type alias type =>?[-A, +B] = PartialFunction[A, B]. This alias may be added to Predef in the future but until it is you can add it yourself.
1. scala> type =>?[-A, +B] = PartialFunction[A, B]
2. defined type alias \$eq\$greater\$qmark
3. scala> val i : (Any =>? Unit) = {case x:Int => println("int found")}
4. i: =>?[Any,Unit] = < function1>
5. scala> val j : (Any =>? Unit) = {case x:Double => println("Double found")}
6. j: =>?[Any,Unit] = < function1>
7. scala> val * : (Any =>? Unit) = {case x=> println("Something else found")}
8. *: =>?[Any,Unit] = < function1>
9. scala> (i orElse j orElse *)(1)
10. int found
11. scala> (i orElse j orElse *)(1.0)
12. Double found
13. scala> (i orElse j orElse *)(true)
14. Something else found
15. scala> def =>?[A, B](id : A =>? B) = id
16. \$eq\$greater\$qmark: [A,B](id: =>?[A,B])=>?[A,B]
17. scala> ( =>?[Any, Unit]{case s : String => println("String found")} orElse j orElse *)("hello")
18. String found

1. A nice alias indeed, but with one trap. The built-in => is right associative whereas the one defined above will be left associative. This is one reason why the latter was removed from Predef after making it in there at one stage.

2. To make what inkytonik said clearer, consider this:

A => B => C
A =>? B =>? C

They translate, respectively, into:

Function1[A, Function1[B, C]]
PartialFunction[PartialFunction[A, B], C]

3. It looks like if you add a : that changes the associativity:

scala> type =>?:[-A, +B] = PartialFunction[A, B]
defined type alias \$eq\$greater\$qmark\$colon

scala> class X { val x : Int =>?: Unit =>?: Any = null }
defined class X

scala> new X().x
res2: =>?:[Int,=>?:[Unit,Any]] = null

4. I still say that =?> scans better visually. And it has embedded meaning: if you pass this to something that's expecting a Function1, you may have a nice mushroom cloud in the middle of things!