Использование неявно метода
Наиболее распространенным и общим подходом является использование неявно метода , определенного в Predef:
def add[T: Numeric](x: T, y: T) = implicitly[Numeric[T]].plus(x,y)
Очевидно, это несколько многословно и требует повторения имени класса типа.
Ссылка на параметр доказательства ( не! )
Другой альтернативой является использование имени параметра неявного доказательства, автоматически сгенерированного компилятором:
def add[T: Numeric](x: T, y: T) = evidence$1.plus(x,y)
Удивительно, что этот метод является даже законным, и на него не следует полагаться на практике, поскольку имя параметра доказательства может измениться.
Контекст высшего рода (, представляющий context
метод )
Вместо этого можно использовать расширенную версию метода implicitly
. Обратите внимание, что неявный метод определяется как
def implicitly[T](implicit e: T): T = e
Этот метод просто полагается на то, что компилятор вставляет неявный объект правильного типа из окружающей области видимости в вызов метода, а затем возвращает его. Мы можем сделать немного лучше:
def context[C[_], T](implicit e: C[T]) = e
Это позволяет нам определить наш add
метод как
def add[T: Numeric](x: T, y: T) = context.plus(x,y)
Параметры типа метода context
Numeric
и T
выводятся из области видимости! К сожалению, есть обстоятельства, при которых этот context
метод не будет работать. Например, когда параметр типа имеет несколько границ контекста или существует несколько параметров с разными границами контекста. Мы можем решить последнюю проблему с немного более сложной версией:
class Context[T] { def apply[C[_]]()(implicit e: C[T]) = e }
def context[T] = new Context[T]
Эта версия требует, чтобы мы каждый раз указывали параметр типа, но обрабатывает несколько параметров типа.
def add[T: Numeric](x: T, y: T) = context[T]().plus(x,y)