Wnioskowanie typu Scala na typ egzystencjalny
Rozważ następujący fragment kodu, który jest zredukowaną wersją mojego pierwotnego problemu:
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
}
To nie powiedzie się z błędem czasu kompilacjivariable
wywnioskowano, że ma typRandomVariable[_0]
gdyAssignment
wymagany typAny
. Dlaczego jest value
nie wywnioskowano również, że ma typ _0
? Próbowałem podać nazwę typu egzystencjalnego, aby dać podpowiedź kompilatorowicase (variable: RandomVariable[T forSome {type T}]) :: tail =>
ale także nie skompilowałby się (mówiąc, że nie mógł znaleźć typu T, który byłby również zainteresowany wyjaśnieniem).
Aby uzyskać więcej motywacji, rozważ, kiedy przechwycimy parametr typu w następujący sposób:
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)
Kompiluje się bez ostrzeżeń / błędów. Czy jest coś, co mogę zmodyfikować w pierwszym przykładzie, aby nie wymagać tej dodatkowej funkcji?
EDYTOWAĆ: Aby być bardziej wyraźnym, chcę wiedzieć dlaczegovalue
nie jest uważany za typ_0
nawet jeślivariable
jest typu_0
a każda wartość pochodzi od aList[_0]
wvariable
. Chciałbym również wiedzieć, czy są jakieś dodatkowe sposoby, aby powiedzieć kompilatorowi o tym fakcie (poza przechwytywaniem typu w funkcji, którą podałem powyżej).