Implicit double dispatch revisited

This is the code for the blog entry implicit double dispatch revisited.

package michid;

object Converters2 {

  abstract class Dispatcher[T](value: T) {
    def dispatch()
    def dispatch(l: List[T])
  }

  implicit def string2Disp(value: String) = new Dispatcher(value){
    def dispatch() = println("String: " + value)
    def dispatch(l: List[String]) =  println("List[String]: " + l)
  }

  implicit def int2Disp(value: int) = new Dispatcher(value){
    def dispatch() = println("Integer: " + value)
    def dispatch(l: List[int]) = println("List[Integer]: " + l)
  }

  implicit def list2Disp[T](value: List[T])(implicit x2Disp: T => Dispatcher[T]) = new Dispatcher(value) {
    def dispatch() = x2Disp(null.asInstanceOf[T]).dispatch(value)
    def dispatch(l: List[List[T]]) = println("List[List[_]]: " + l)
  }

}

object Poly2 {
  import michid.Converters2._

  def foo[T <% Dispatcher[T] forSome { type T <: List[_] }](x: T) = x.dispatch()

  def main(args: Array[String]) {
    val ints: List[int] = Nil
    foo(ints)
    val strings: List[String] = Nil
    foo(strings)

    // foo("A String")   // Won't compile
    // foo(42)           // Won't compile  

    foo("one"::"two"::"three"::Nil)
    foo(1::2::3::Nil)

    foo((1::2::3::Nil)::(4::5::6::Nil)::Nil)
    foo(("one"::"two"::Nil)::("three"::"four"::Nil)::Nil)
  }
}

One response

9 03 2009

Leave a comment