Как определить метод scala с типом param, который не может быть Any - PullRequest
9 голосов
/ 17 июня 2019

В следующем примере я хочу определить метод contains, который не компилируется, если a и b не имеют одинаковый базовый тип.

  • В contains1 impl, если a равно Seq[Int] и b равно String, T выводится как Any и компилируется.Это не я хочу.
  • В contains2 impl, если a равно Seq[Int], а b равно String, то оно не компилируется.Поведение - это то, что я хочу.
def contains1[T](a: Seq[T], b: T): Boolean = a.contains(b)

println(contains1(Seq(1,2,3), "four")) // false

def contains2[T: Ordering](a: Seq[T], b: T): Boolean = a.contains(b)

println(contains2(Seq(1,2,3), "four")) // compilation error
// cmd7.sc:1: No implicit Ordering defined for Any.
// val res7 = isMatched(Seq(1,2,3), "s")
                    ^
// Compilation Failed

Однако есть ли более простой способ добиться того же поведения, что и в contains2?Ordering привязка к контексту смущает меня, так как метод не имеет ничего общего с сортировкой / упорядочением.

1 Ответ

9 голосов
/ 17 июня 2019

Вы можете использовать ограничения обобщенного типа оператор =:=.

Например:

def contains[A,B](a: Seq[A], b: B)(implicit evidence: A =:= B): Boolean = a.contains(b)

и затем:

println(contains1(Seq(1,2,3), "four")) //fails with Cannot prove that Int =:= String.
println(contains1(Seq("one"), "four")) //returns false
println(contains1(Seq("one", "four"), "four")) //true

Подробнее об ограничениях обобщенного типа здесь и здесь .

Как заметил LuisMiguelMejíaSuárez, вы также можете рассмотреть возможность использования B <:< A вместо A =:= B. Я не буду подробно останавливаться на различиях между этими двумя, потому что это описано в связанном ответе и статье, но вкратце, <:< также позволит всем B, которые являются подтипом A, в то время как =:= нужны типы для соответствия точно.

...