Идиоматический способ ветвления в зависимости от существования доказательства типа в Scala

#scala #types #implicits

#scala #типы #подразумевает

Вопрос:

Я не раз писал следующий уродливый шаблон:

 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
  }
}
  

Еще хуже, когда ev != null я иногда писал ереси, такие как someB.asInstanceOf[A] .

Комментарии:

1. Почему бы просто не относиться к нему так же, как вы должны относиться к возможности null где-либо еще (т. Е. Option(ev) )?

Ответ №1:

Просто используйте класс типа,

 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()
}
  

Комментарии:

1. Должен ли этот код << признак Something [A, B](неявный ds: doStuff[A, B]) { def doStuff: Unit = doStuff() }>> измениться на << класс Something3[A, B] { def doStuff()(неявный ds: doStuff[A, B]) : Unit = ds.doStuff } >>

2. @Cloudtech это зависит от контекста, но если, как здесь, экземпляр может быть исправлен раз и навсегда при Something создании экземпляра, то зачем откладывать его и, возможно, оплачивать стоимость его вызова при каждом вызове метода?