РЕДАКТИРОВАТЬ: Добавлено в информации о F[_]
Вот настройки.У нас есть родительский класс, который содержит тип, и метод, который обрабатывает проекцию типа этого во всех родительских экземплярах:
class Parent[F[_]] {
// These depend on information from Parent (ie F) so
// cannot be moved outside
trait Inner { def execute[A]: F[A] }
case class Foo(i: Int) extends Inner { ... }
case class Bar(s: String) extends Inner { ... }
def process(value: Parent#Inner): Unit = value match {
case Foo(_) => println("integer")
case Bar(_) => println("string")
}
}
Проблема заключается в том, что внутри соответствия регистров ссылки на Foo
иBar
являются this.Inner
, а не Parent#Inner
.Таким образом, происходит следующее:
val foo = (new Parent[IO]).Foo(5)
val processer = new Parent[IO]
processer.process(foo) // match error
Одним из способов решения этой проблемы является изменение def process
на:
def process(value: Parent#Inner): Unit = value.asInstanceOf[this.Inner] match {
case Foo(_) => println("integer")
case Bar(_) => println("string")
}
(обратите внимание на новый .asInstanceOf
).
Однако это неудовлетворительно.
Помимо извлечения def process
в сторонний класс, есть ли лучший способ достичь желаемого поведения?
РЕДАКТИРОВАТЬ:
Классы, к сожалению, должны быть определены внутри Parent
из-за зависимости от F[_]
.Теоретически мы могли бы переместить их наружу, как предполагает первоначальный ответ, но это повлекло бы за собой слишком много работы и разнообразия в других местах, поскольку нам нужно было бы параметризовать каждый Inner
подкласс с помощью F[_]
EDIT 2:
Одним из возможных решений является переформулировка process
следующим образом:
def process(value: Parent#Inner): Unit = value match {
case _: Parent[F]#Foo => println("integer")
case _: Parent[F]#Bar => println("string")
}
Но это означает, что мы не можем использовать метод неприменения Foo
.Недопустимо следующее:
case Parent[F]#Foo(_) => println("integer")
В случае, когда вместо Foo
указано, например, Foo[A, B, C](a: A, b: B, c: C)
, это будет означать, что оператором соответствия становится:
case _: Parent[F]#Foo[A, B, C] @unchecked => ...
, который вводит намного большесложность и вероятность сбоя в сопоставлении с образцом.