Scala type inference on an existential type

老子叫甜甜 提交于 2019-12-01 22:13:58

Another compiling solution, that is cleaner(?) than using a function to capture the type. However, it makes it even more puzzling as to why type inference fails in the original case.

def enumerateAll(vars: List[RandomVariable[_]], evidence: List[SingleAssignment[_]]): Double = vars match {
  case (variable@RandomVariable(values)) :: tail =>
    val enumeration = for {value <- values
      assignment = SingleAssignment(variable, value)
      extendedEvidence = evidence :+ assignment
    } yield enumerateAll(tail, extendedEvidence)
    enumeration.sum
  case Nil => 1.0
}

It also returns the following warning:

scala: match may not be exhaustive.
It would fail on the following input: List((x: questions.RandomVariable[?] forSome x not in questions.RandomVariable[?]))
  def enumerateAll(vars: List[RandomVariable[_]], evidence: List[SingleAssignment[_]]): Double = vars match {

Which I'm unable to decipher as of this posting. Also, running it with a few test cases produces the desired result without a match error using RandomVariables of int, double, and string in the parameter list.

Shouldn't you bind the types of RandomVariable and Assignment together?

 def [A] enumerateAll(vars: List[RandomVariable[A]], evidence: List[Assignment[A]]): Double = 

actually, you can be more permissive and just say

 def [A] enumerateAll(vars: List[RandomVariable[A]], evidence: List[Assignment[_ <: A]]): Double = 
Avilo

The error code gives some indication of a solution.

<console>:15: error: type mismatch;
 found   : RandomVariable[_0] where type _0
 required: RandomVariable[Any]
Note: _0 <: Any, but class RandomVariable is invariant in type A.
You may wish to define A as +A instead. (SLS 4.5)
           extendedEvidence = evidence :+ Assignment(variable, value)

It's telling you that it saw a more specific type than it inferred and even suggested to make RandomVariable allow a covariant A. This would allow it to vary the type downward when required.

case class RandomVariable[+A](values: List[A])

Alternatively, you can explicitly set the generic type in enumerateAll for both parameters. In that way it can infer the appropriate type instead of being forced to infer Any. This definition doesn't require the RandomVariable covariant change as both parameters are of the same type.

def enumerateAll[A](vars: List[RandomVariable[A]], evidence: List[Assignment[A]]): Double = 

This question may help with the explanation. Why doesn't the example compile, aka how does (co-, contra-, and in-) variance work?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!