Вкратце: следующее не компилируется (причина ниже), как я могу заставить его работать?Scala: повторное использование родового в результате зависимого от пути типа в зависимом от пути контексте
trait Simulator {
type CM[T]
def useCM(v: CM[_])
}
case class CMH[S <: Simulator,T](cm: S#CM[T])
class SimIterator[S <: Simulator](val sim: S, val cmhs: Seq[CMH[S,_]]) {
cmhs foreach { cmh => sim.useCM(cmh.cm) }
/*
compile time error:
type mismatch; found : cmh.cm.type (with underlying type S#CM[_$2]) required:
SimIterator.this.sim.CM[_] Note: _$2 <: Any (and cmh.cm.type <: S#CM[_$2]),
but type CM is invariant in type T. You may wish to define T as +T instead.
(SLS 4.5)
*/
}
Идея структуры является то, что CMH
скрывает T
Определённого поведения от SimIterator
, где, как последние обрабатывают общие задачи. S
используется для принудительного vlaues в CMH
, чтобы иметь нужный тип без экземпляра Simulator
.
В foreach
, похоже, проблема с подтипированием связана с CM
. Если S#CM
является конкретным типом, нам необходимо sim.CM =:= S#CM
. Однако, обратите внимание на следующее:
object Test extends Simulator {
type CM[T] = Option[T]
def useCM(v: CM[_]) = println(v)
def mkCM[T]: CM[T] = None
CMH[Simulator,AnyRef](mkCM[AnyRef])
}
Мы имеем теперь CMH
, что мы можем перейти в SimIterator
вместе с любым Simulator
. По-видимому, типизация SimIterator
не является достаточно ограничительной. Как можно выразить (и использовать) S =:= sim.type
?
ОБНОВЛЕНИЕ
Это работает, но не может быть использовано в конструкторе (незаконный зависимый типа метода: параметр появляется в типе другого параметра в той же самой секции или раньше)
class SimIterator(val sim: Simulator) {
def doIt(cmhs: Seq[CMH[sim.type,_]]) {
cmhs foreach { cmh => sim.useCM(cmh.cm) }
}
}
Верхний пример работает, но не что я хочу. cmhs
должен быть передан при строительстве.
Благодарим вас за ответ. «Симулятор» используется в шаблоне пирога (для испечения конкретного симулятора с разными моделями), откуда и возникает член типа. 'SimIterator' находится за пределами области торта и может использовать некоторые конкретные реализации' Simulator' (ограничения типов, не показанные в этом примере) для создания итерационных симуляций при сохранении данных 'CM' (типа' T') между прогонами , Добавление параметра типа в «Симулятор» не ухудшается с точки зрения «SimIterators», но полностью нарушает абстракцию типа образца пирога. 'cmhs' является гетерогенным в' T', следовательно, проекция. – gzm0
@ gzm0 Хорошо, справедливо. Это имеет смысл. Я отредактировал свой ответ с возможным решением. Удачи вам в торте :-) Я лично стараюсь избегать этой картины как можно больше, чтобы избежать этой пекарни обреченности. –
Большое спасибо, это имеет смысл. Но разве это не просто синтаксическое ограничение? Во вторичном конструкторе из моего ответа вполне можно заставить тип, как я хочу. Есть ли причина, по которой это невозможно распространить на основной конструктор? – gzm0