1

I find myself more than once writing the following ugly pattern:

class Something[A, B](implicit ev: A =:= B = null) {
  ...

  def doStuff {
    if (ev == null) ... // know that A is not the same as B
    else ...            // safely assume A is equal to B
  }
}

Even worse, when ev != null, I would sometimes write heresies such as someB.asInstanceOf[A].

kiritsuku
  • 52,967
  • 18
  • 114
  • 136
Hugo Sereno Ferreira
  • 8,600
  • 7
  • 46
  • 92

1 Answers1

6

Just use a type class,

trait DoStuff[A, B] {
  def apply(): Unit
}

trait DoStuff0 {
  implicit def neDoStuff[A, B]: DoStuff[A, B] =
    new DoStuff[A, B] { def apply(): Unit = ... body of your ev == null case ...
}

object DoStuff extends DoStuff0 {
  implicit def eqDoStuff[A]: DoStuff[A, A] =
    new DoStuff[A, A] { def apply(): Unit = ... body of your ev != null case ...
}

class Something[A, B](implicit ds: DoStuff[A, B]) {
  ...
  def doStuff: Unit = ds()
}
kiritsuku
  • 52,967
  • 18
  • 114
  • 136
Miles Sabin
  • 23,015
  • 6
  • 61
  • 95
  • 1
    Should this code << trait Something[A, B](implicit ds: DoStuff[A, B]) { def doStuff: Unit = DoStuff() } >> change to << class Something3[A, B] { def doStuff()(implicit ds: DoStuff[A, B]) : Unit = ds.doStuff } >> – Xiaohe Dong Jul 02 '14 at 04:33
  • @Cloudtech it depends on the context but if, as here, the instance can be fixed once and for all when `Something` is instantiated, then why defer it and possibly pay the cost of summoning it each time the method is invoked? – Miles Sabin Jul 02 '14 at 20:14