Невозможно доказать, что "Tuple2" <: <(T, U) - PullRequest
6 голосов
/ 27 июня 2019

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

код

class Element[T] extends AnyRef { }

class Sample
{
    def makeList(x:Int): Element[_] = {
        x match {
            case 1 => new Element[Boolean]
            case 2 => new Element[(Boolean, Boolean)]
        }
    }

    val input = Map(1 -> "one",2 -> "two")

    val output = input.map(e => e._1 -> makeList(e._1)).toMap
}

sbt compile

sbt:root> ~compile
[info] Compiling 1 Scala source to /Users/tda0106/test/scala/target/scala-2.12/classes ...
[error] /Users/tda0106/test/scala/src/main/scala/Test.scala:14:57: Cannot prove that (Int, Element[_$1]) forSome { type _$1 } <:< (T, U).
[error]     val output = input.map(e => e._1 -> makeList(e._1)).toMap
[error]                                                         ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 1 s, completed Jun 27, 2019, 2:38:14 PM

Похоже, что проблема связана с forSome { type _$1 }, иначе она должна совпадать. Когда я впервые попытался воспроизвести его, я использовал List вместо Element, и он скомпилировался. Похоже, что разница в том, что List объявлен как List[+T], и здесь + важен.

Element из сторонней библиотеки, поэтому изменить ее сложно.

В чем проблема, с которой я здесь сталкиваюсь, и есть ли простой способ ее исправить?

Версия Scala: 2.12.8

1 Ответ

6 голосов
/ 27 июня 2019

Scala иногда не понимает вывод типа, когда вы делаете что-то с экзистенциалами (что и есть Element[_]).Быстрая явная сигнатура типа исправит это.

val output = input.map(e => e._1 -> makeList(e._1)).toMap[Int, Element[_]]

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

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