В Scala, почему я получаю это "полиморфное выражение не может быть создано для ожидаемого типа"? - PullRequest
20 голосов
/ 13 июля 2011

Почему в Scala 2.9.0.1?

scala> def f(xs: Seq[Either[Int,String]]) = 0
f: (xs: Seq[Either[Int,String]])Int

scala> val xs = List(Left(0), Right("a")).iterator.toArray
xs: Array[Product with Serializable with Either[Int,java.lang.String]] = Array(Left(0), Right(a))

scala> f(xs)
res39: Int = 0

scala> f(List(Left(0), Right("a")).iterator.toArray)
<console>:9: error: polymorphic expression cannot be instantiated to expected type;
 found   : [B >: Product with Serializable with Either[Int,java.lang.String]]Array[B]
 required: Seq[Either[Int,String]]
       f(List(Left(0), Right("a")).iterator.toArray)
                                            ^

обновление происходит следующее: Дебилски предлагает лучший пример (не уверен на 100%, что это демонстрирует тот же основной феномен):

Seq(0).toArray : Seq[Int] // compiles
Seq(Some(0)).toArray : Seq[Option[Int]] // doesn't

Ответы [ 3 ]

5 голосов
/ 13 июля 2011

Лучший человек, который может объяснить это, - Адриан Мурс, и он уже сделал это здесь, в Переполнении стека - ищите ответы от него, и вы найдете это.

В любом случае, проблема в том, что типList(Left(0), Right("a")).iterator.toArray не может быть выведено в границах, ожидаемых f.Он не соответствует Seq[Either[Int, String]] без неявного преобразования, и не может быть применено неявное преобразование, поскольку его (тип) невозможно определить.Это похоже на проблему с яйцом и курицей.

Если вы используете <% или присваиваете ему значение val, вы нарушаете цикл в выводе.

3 голосов
/ 13 июля 2011

Это не имеет ничего общего с Either, а скорее с обработкой Array. Если вы конвертируете его вручную в Seq, это сработает:

scala> f(xs.toSeq)
res4: Int = 0

Scala Array - это не Seq (потому что на самом деле это массив Java). Но WappedArray есть. Вы также можете переопределить вашу функцию f имеет:

scala> def f[A <% Seq[Either[Int,String]]](xs: A) = 0
f: [A](xs: A)(implicit evidence$1: (A) => Seq[Either[Int,String]])Int

scala> f(xs)
res5: Int = 0

Кстати, нет необходимости получать итератор перед вызовом toArray.

0 голосов
/ 13 июля 2011

Я считаю, что это потому, что вы не можете превратить массив в массив, но вы можете преобразовать последовательность в массив.Метод хочет последовательность, которую он может использовать для создания массива.

Суть в том, чтобы проверить сигнатуры метода и не угадать, что они основаны на имени метода.

Важная часть такова:

found   : [B >: Product with Serializable with Either[Int,java.lang.String]]Array[B]
 required: Seq[Either[Int,String]]
       f(List(Left(0), Right("a")).iterator.toArray)

toArray метод хочет Seq (поэтому список будет в порядке) и возвращает массив.Вы передали ему массив, и он не знает, что делать.Либо сначала сделайте Array в Seq, либо просто полностью пропустите метод toArray.

Если вы вернетесь на один шаг назад, станет ясно, что метод iterator берет ваш List и возвращает массив.Каждый вызов метода является вызовом функции.

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