Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot prove that "a Tuple2" <:< (T, U)

Tags:

scala

I am trying to build a map from an input map, but the compiler is unable to prove that a 2-element tuple is a 2-element tuple.

Code

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

It appears that the problem is related to the forSome { type _$1 }, as otherwise it should match. When I first tried to reproduce it, I used List instead of Element and it compiled. It appears that the different is that List is declared as List[+T] and the + is important here.

Element is from a third party library, so changing it is difficult.

What is the problem that I am running into here, and is there a simple way to fix it?

Scala version: 2.12.8

like image 803
Troy Daniels Avatar asked Jun 27 '19 18:06

Troy Daniels


1 Answers

Scala gets fickle about type inference sometimes when you're doing things with existentials (which is what Element[_] is). A quick explicit type signature will fix that right up.

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

All you're doing is telling the compiler what types you want for the keys and values. The reasons why it can't infer this are long and complicated, but as a general rule once you start throwing underscores in your types, you're going to lose some inference capabilities.

like image 79
Silvio Mayolo Avatar answered Nov 11 '22 15:11

Silvio Mayolo