2

Scala 11.2 is giving me this error:

error: type mismatch;
 found   : Seq[Some[V]]
 required: Seq[Option[?V8]] where type ?V8 <: V (this is a GADT skolem)
            val output = f(ivs.map(iv => Some(iv.get._1)))
                                   ^

First off, this seems like a strange error message: Doesn't Seq[Some[V]] conform to Seq[Option[V]]?

Here are the parts of the surrounding code that seem relevant:

  def evalDependencyTree[V]
    (linkRelevance: LinkInfo => Option[LinkStrength])
    (dtree: DependencyTree[V, LinkInfo], strengthSoFar: LinkStrength = 1.0)
  : Option[(V, LinkStrength)] = dtree match {
    . . .
    case DFunction(f, inputs) => {
      val ivs = inputs.map { input =>
        evalDependencyTree(linkRelevance)(input, strengthSoFar) // <-- Recursive call
      }
      val output = f(ivs.map(iv => Some(iv.get._1))) // <-- The line with the error
      . . .
    }
  }

  trait DependencyTree[+V, +L]

  case class DFunction[V, L](
    f: Seq[Option[V]] => Option[V], inputs: Seq[DependencyTree[V, L]])
    extends DependencyTree[V, L]

My (very limited) understanding of GADT skolems is that they're types defined by the compiler during type inference, which copy an existing type argument in order to prevent that type from "escaping" its scope, as in a recursive call—that is, to prevent its being referred to from a wider scope that has no access to the type.

I don't see how V could refer to different types in different scopes here. The recursive call to evalDependencyTree has the same type argument, V, as the current call to evalDependencyTree. I tried explicitly writing evalDependencyTree[V] for the recursive call, but the compiler returned the same error message. This code did work when evalDependencyTree did not have a type argument; in that version, dtree was hard-coded to DependencyTree[Int, LinkInfo].

What type is trying to escape? Or rather, what am I doing wrong?

Ben Kovitz
  • 4,279
  • 1
  • 17
  • 40

1 Answers1

1

I found a workaround myself: explicitly spell out the full type of f in the pattern-match, like this:

case DFunction(f: Seq[Option[V]] => Option[V], inputs) => . . .

This works, but I'm not accepting it as an answer because I don't have an explanation of why it's necessary. I still don't know when to expect this kind of error or what causes it. If you know, please post an answer!

Also, I would have thought that most of the type explicitly provided for f would have been lost by type erasure. So, there are two important things I can't explain about this workaround.

Ben Kovitz
  • 4,279
  • 1
  • 17
  • 40
  • Found your question in the context of [this question](https://stackoverflow.com/questions/41183928/scala-properly-defining-a-empty-value-for-a-abstract-data-type) and I think that you could easily build an analogous classCastException thing as the one in [my answer there](http://stackoverflow.com/a/41184478/614394) – Eduardo Pareja Tobes Dec 16 '16 at 17:04