Общий метод с ошибками `can not resolve symbol 'в Scala

Мне нужно получить общий метод проверки, который можно использовать следующим образом:

check[Int](10, 1, 5) и check[Double](10.0, 1.0, 5.0).

Я пробовал этот код:

trait RangeChecker {
  def check[T <: AnyVal](value:T, mini:T, maxi:T) : Boolean = {
    (value >= mini && value <= maxi)
  }
}

Однако я получаю ошибки Cannot resolve symbol для >=, && и <=. Что может быть неправильным?

enter image description here

Ответ 1

Когда вы пишете

def check[T <: AnyVal] ...

вы определяете метод для all подтипов AnyVal. Однако ваша реализация использует два метода (<= и >=), которые доступны только для подмножества типов, а именно тех, которые поддерживают упорядочение.

Итак, вы должны указать, что метод применяется к типам all, для которых существует , или другими словами

def check[T](value: T, min: T, max: T)(implicit ev: T => Ordered[T]): Boolean =
  value >= min && value <= max

Этот синтаксис эквивалентен представлению (<%)

def check[T <% Ordered[T]](value: T, min: T, max: T): Boolean = ...

но поскольку ограничения просмотра устарели, вам следует избегать этого.


Другой вариант - использовать Ordering таким образом

def check[T](value: T, mini: T, maxi: T)(implicit ord: Ordering[T]): Boolean = {
  import ord.mkOrderingOps
  value >= mini && value <= maxi
}

где импорт ord.mkOrderingOps дает вам возможность использовать обычные методы >= и <=.

Другая эквивалентная альтернатива, использующая прямой контекст:

def check[T: Ordering](value: T, mini: T, maxi: T): Boolean = {
  val ord = implicitly[Ordering[T]]
  import ord.mkOrderingOps
  value >= mini && value <= maxi
}

Ответ 2

Попробуйте следующее:

def check[T <% Ordered[T]](value: T, mini: T, maxi: T): Boolean = {
    (value >= mini && value <= maxi)
  }

Операторы <= и >= определены как часть Упорядоченного признака, а не AnyVal.

EDIT: см. scala API docs здесь и здесь

EDIT2: Заменено <: с <%

Ответ 3

AnyVal не требуются для поддержки таких операций, как >=. Вот почему он не будет работать, как вы пробовали. К сожалению, нет суперкласса всех упорядочиваемых AnyVal s.

Вместо этого Ordering:

def check[T](value: T, low: T, high: T)(implicit ord: Ordering[T]): Boolean = {
  ord.gteq(value, low) && ord.lteq(value, high)
}

Вам часто не нужно явно указывать тип T, когда вы вызываете его:

scala> check(1, 2, 3)
res0: Boolean = false
scala> check(3, 2, 3.5)
res1: Boolean = true