Рассмотрим следующий фрагмент кода, который является уменьшенной версией моей исходной проблемы:
case class RandomVariable[A](values: List[A])
case class Assignment[A](variable: RandomVariable[A], value: A)
def enumerateAll(vars: List[RandomVariable[_]], evidence: List[Assignment[_]]): Double =
vars match {
case variable :: tail =>
val enumerated = for {value <- variable.values
extendedEvidence = evidence :+ Assignment(variable, value)
} yield enumerateAll(tail, extendedEvidence)
enumerated.sum
case Nil => 1.0
}
Это не выполняется с ошибкой времени компиляции, в которой variable
было установлено, что имеет тип RandomVariable[_0]
, когда Assignment
требуется тип Any
. Почему value
также не предполагается, что у вас есть тип _0
? Я попытался присвоить имя экзистенциального типа, чтобы дать подсказку для компилятора с помощью case (variable: RandomVariable[T forSome {type T}]) :: tail =>
, но это также не будет компилироваться (говоря, что он не мог найти тип T, о котором мне также было бы интересно объяснение).
Для дальнейшей мотивации рассмотрим, когда мы фиксируем параметр типа следующим образом:
case variable :: tail =>
def sum[A](variable: RandomVariable[A]): Double = {
val enumerated = for {value <- variable.values
extendedEvidence = evidence :+ Assignment(variable, value)
} yield enumerateAll(tail, extendedEvidence)
enumerated.sum
}
sum(variable)
Это компилируется без предупреждений/ошибок. Есть ли что-то, что я могу изменить в первом примере, чтобы не требовать этой дополнительной функции?
EDIT. Чтобы быть более явным, я хочу знать, почему value
не выводится типа _0
, хотя variable
имеет тип _0
, и каждое значение приходит от a List[_0]
в variable
. Кроме того, я хотел бы знать, есть ли какие-либо дополнительные способы сообщить компилятору об этом факте (кроме того, что он записывает тип в функции, как я уже говорил выше).