Этого можно добиться, определив следующий тип фантома:
sealed class DefaultsTo[A, B]
trait LowPriorityDefaultsTo {
implicit def overrideDefault[A,B] = new DefaultsTo[A,B]
}
object DefaultsTo extends LowPriorityDefaultsTo {
implicit def default[B] = new DefaultsTo[B, B]
}
Тогда ваш метод может быть написан
def apply[A]( id: String )( implicit e: A DefaultsTo String,
processor: Processor[A] ) =
processor( data get id )
Определение overrideDefault
гарантирует, что для любых двух указанных типов, A
и B
, компилятор всегда может предоставить объект типа DefaultsTo[A, B]
(например, DefaultsTo[Int, String]
). Однако, если один из двух типов не указан (например, DefaultsTo[A, String]
), компилятор предпочтет идентифицировать эти два типа (предоставив, например, DefaultsTo[String, String]
и, таким образом, выведя String
для неуказанного типа A
).
Как отметил Нафтоли Гугенхайм в этой ветке списка рассылки , вы также можете получить хороший синтаксис для использования с границами контекста:
class Has[B] {
type AsDefault[A] = A DefaultsTo B
}
def apply[A : Has[String]#AsDefault : Processor](id: String) =
implicitly[Processor[A]].apply(data get id)