Универсальный метод, преобразуемый в структурный тип в скале - PullRequest
8 голосов
/ 08 декабря 2011

Почему я не могу сделать это:

def compare[A <% { def toInt: Int }, 
            B <% { def toInt: Int }]
           (bs: Seq[A], is: Seq[B]): Boolean = { 
  bs.toArray.zip(is) forall { p => p._1.toInt == p._2.toInt } 
}

Чтобы сравнить любую последовательность типов, конвертируемых в Int?Как я могу реализовать подобный шаблон?


Обновление: это должно работать Message.compare(List(1.0, 2.0, 3.0), List(0, 0, 0))

Ответы [ 3 ]

9 голосов
/ 08 декабря 2011

Поскольку вы имеете дело с Array s, вам нужно ClassManifest s.

def compare[A <% { def toInt: Int } : ClassManifest, 
            B <% { def toInt: Int } : ClassManifest]
            (bs: Seq[A], is: Seq[B]): Boolean = { 
  (bs.toArray, is).zipped.forall(_.toInt == _.toInt)
}

Сообщение об ошибке компилятора в этом случае не может быть более ясным IMO.

РЕДАКТИРОВАТЬ:

Вам на самом деле не нужно конвертировать последовательности в массивы.Следующее работает просто отлично.

def compare[A <% { def toInt: Int }, 
            B <% { def toInt: Int }]
           (bs: Seq[A], is: Seq[B]): Boolean = { 
      (bs, is).zipped.forall(_.toInt == _.toInt)
}
2 голосов
/ 04 января 2012

Хороший пример того, в чем проблема, кажется, делает это:

val a = implicitly[Int => { def toInt : Int }]
a(1).toInt

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

Вы можете добиться желаемого эффекта, используя классы типов: следующий код работает во всех ваших примерах:

def compare[A : Numeric, B : Numeric](bs : Seq[A], cs : Seq[B]) = {
  (bs, cs).zipped.forall(implicitly[Numeric[A]].toInt(_) == implicitly[Numeric[B]].toInt(_))
}

Это также должно быть быстрее, чем версия, использующая структурные типы. Если вам нужно добавить свои собственные типы, которые должны быть преобразованы в целые числа, вы можете предоставить свидетельство для числового класса типов таким же образом, как это делается в https://lampsvn.epfl.ch/trac/scala/browser/scala/tags/R_2_9_1_final/src//library/scala/math/Numeric.scala#L1 для стандартных значений.

2 голосов
/ 08 декабря 2011

У меня нормально работает, когда убираю ненужные toArray

def compare[A <% { def toInt: Int }, B <% { def toInt: Int }](bs: Seq[A], is: Seq[B]): Boolean = { bs.zip(is) forall { p => p._1.toInt == p._2.toInt } }
Class A{def toInt = 4}
Class B(i: Int) {def toInt = i}
compare (List(new A, new A), List(new B(3), new B(4))) //false
compare (List(new A, new A), List(new B(4), new B(4))) //true

Преобразование Seq в массив потребует добавления неявного ClassManifest, однако Scala не позволяет смешивать их с границами представления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...