Вы пропустили ключевые слова case
в своем сопоставлении с шаблоном, которые очень важны!
Все, что вам нужно, это чтобы тип параметра коллекции мог использовать метод compare
. В Scala есть две системы сравнения: расширение Ordered
или использование Ordering
. Между ними есть неявные преобразования, поэтому не имеет большого значения, какой вы выберете; первое, возможно, легче понять.
Во-первых, используя Ordered
:
def myMaxBy[A <% Ordered[A]](xs: List[A]) = {
(List(xs.head) /: xs.tail) { (acc, y) =>
y compare acc.head match {
case 1 => List(y)
case 0 => y :: acc
case -1 => acc
}
}
}
Здесь мы даем наш универсальный тип A
a , связанный с представлением , используя <%
, что означает «можно видеть как». Это является более общим, чем использование верхней границы <:
, и полезно для классов, которые сами не являются Ordered
, но имеют неявные преобразования в классы Ordered
, например, Int
до RichInt
.
В качестве альтернативы, если вы хотите, чтобы гибкость позволяла изменять критерии заказа, вы можете написать это так:
def myMaxBy[A](xs: List[A])(implicit ord: Ordering[A]) = {
(List(xs.head) /: xs.tail) { (acc, y) =>
ord.compare(y, acc.head) match {
case 1 => List(y)
case 0 => y :: acc
case -1 => acc
}
}
}
При вызове, если в области видимости есть неявное значение Ordering[A]
, вы можете не указывать второй аргумент. Этот второй способ также имеет то преимущество, что вы можете определить Ordering
для произвольных классов, независимо от того, поддерживают ли они его или нет.
Вы можете вызывать оба, используя, например, myMaxBy(List(1,2,3,4,3,4))
. Во втором, если вы хотите, скажем, обратный порядок: myMaxBy(List(1,2,3,4,3,4))(Ordering.Int.reverse)
.
Еще одна вещь, которую вы можете увидеть в этом контексте, это границы контекста . Например. [A: Ordering]
. Это означает то же самое, что и [A](implicit ord: Ordering[A])
, что более кратко, за исключением того, что вы не получаете дескриптор на Ordering
, поэтому вам нужно вызвать его, используя implicitly
. Так что здесь, вероятно, лучше заявить об этом, как указано выше.