Scala: лямбда не может быть приведена к ошибке ClassTag - PullRequest
0 голосов
/ 11 июня 2018

Я пытаюсь объединить границу представления (мотивация использования устаревшей границы будет следовать ниже) с неявным параметром ClassTag.Вот вкратце иерархия моих классов (я опускаю код, который кажется неуместным, вы можете указать, если вам что-то нужно):

abstract class BaseSort [T <% Ordered[T]]{
//some methods
}

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

Из 1-го издания "Scala for the Impatient" (стр. 234):

Отношение <% означает, чтоT может быть преобразован в Comparable [T] посредством неявного преобразования

Тогда в качестве его реализации у меня есть класс MergeSort:

//Segewick and Wayne's implementation re-written in Scala
class MergeSort [T <% Ordered[T]](implicit evidence: ClassTag[T]) extends BaseSort [T]{
  var aux: Array[T] = _

  def sort(a: Array[T]): Array[T] = {
    aux = new Array[T](a.length)
    sort(a, 0, a.length-1)
  }
...
}

Строка комментария перед сигнатурой классаСамо собой разумеется, но я думаю, что это поле var aux: Array[T] = _, где моя проблема начинается.Если я следую книге «Алгоритмы», то не должен пытаться инициализировать это из конструктора.

Наконец, у меня есть вариант реализации MergeSort, который имеет следующую сигнатуру (он переопределяет метод сортировки MergeSort):

class Ex2_2_12[T<% Ordered[T]](implicit evidence: ClassTag[T]) extends MergeSort[T]{
...
}

Теперь, когда я пытаюсь запустить этот тест:

class Ex2_2_12Spec extends BaseSpec{

 ...

  "an array" should "at least be sorted" in {
    val test = "MERGEWITHSHELLSORTEXAMPLE".toCharArray
    val customMergeSort = new Ex2_2_12[Char]
    customMergeSort.sort(test)
    info(s"target array after sorting is ${test.toList}")
    assert(isSorted(test))
  }
}

это то, что мне бросают: -):

[info] an array
[info] - should at least be sorted *** FAILED ***
[info]   java.lang.ClassCastException: ca.vgorcinschi.algorithms_2.Ex2_2_12Spec$$Lambda$18483/698572900 cannot be cast to scala.reflect.ClassTag
[info]   at ca.vgorcinschi.algorithms_2.Ex2_2_12.<init>(Ex2_2_12.scala:21)
[info]   at ca.vgorcinschi.algorithms_2.Ex2_2_12Spec.$anonfun$new$2(Ex2_2_12Spec.scala:13)
[info]   at org.scalatest.OutcomeOf.outcomeOf(OutcomeOf.scala:85)
[info]   at org.scalatest.OutcomeOf.outcomeOf$(OutcomeOf.scala:83)
[info]   at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
[info]   at org.scalatest.Transformer.apply(Transformer.scala:22)
[info]   at org.scalatest.Transformer.apply(Transformer.scala:20)
[info]   at org.scalatest.FlatSpecLike$$anon$1.apply(FlatSpecLike.scala:1682)
[info]   at org.scalatest.TestSuite.withFixture(TestSuite.scala:196)
[info]   at org.scalatest.TestSuite.withFixture$(TestSuite.scala:195)
[info]   ...

Ссылка в трассировке стекастрока 21 является подписью Ex2_2_12.Я попробовал две вещи:

  • Использовать составную (class Ex2_2_12[T<% Ordered[T] with ClassTag[T]]) -такую ​​ошибку
  • удалить неявный параметр ClassTag - тогда я получаю ошибку для указанного выше вспомогательного поля (Array)[T]), что ClassTag не предоставлен.

Я продолжу расследование, но если кто-то может дать мне подсказку или указание, которое будет оценено.

1 Ответ

0 голосов
/ 12 июня 2018

Что ж, в моем случае решение было (из той же книги, но спустя 80 страниц) прочитать устаревшие границы представления и использовать составные границы контекста:

Базовый класс:

abstract class BaseSort [T : Ordering]{

  ...

  def less(v: T, w: T):Boolean = {
    import Ordered._
    v < w
  }
...
}

Один уровень повышения:

class MergeSort [T : ClassTag : Ordering] extends BaseSort [T]{
  var aux: Array[T] = _
...
}

И почти идентично классу, который мне нужен для моего теста:

class Ex2_2_12[T : ClassTag : Ordering] extends MergeSort[T]{...}
...