Извините, мне трудно найти подходящий заголовок для моей проблемы.Неисправность с инкапсулирующими «рекурсивными типами» в Scala
Я хочу моделировать следующее поведение: я разработал «язык» с выражениями, которые инкапсулируют стандартные типы Scala. Выражения могут быть либо переменными, либо последовательностями выражений. В дальнейшем A может быть стандартным типом Scala (а именно Boolean, Int, Double). Я также хочу реализовать метод замены выражений другим в выражениях (особенно в последовательностях). Я пробовал код, который я не могу скомпилировать. Я помещал кавычки, когда я действительно не знаю, какой тип поставить, но все это, вероятно, беспорядочно. У меня есть особые проблемы с вещью Sequence, из-за ее рекурсивного характера.
sealed trait Expression[A] {
def replace[B](a: Expression[B], b: Expression[B]): Expression[?]
}
trait Variable[A] extends Expression[A] {
def replace[B](a: Expression[B], b: Expression[B]) =
if (a == this) b else this
}
case class Sequence[A <: Expression[B]](values: Seq[A]) extends Expression[A] {
def replace[B](a: Expression[B], b: Expression[B]) =
if (a == this) b
else Sequence(values.map(_.replace(a, b)))
}
Я полагаю, конечно, что последовательности ацикличны (последовательность не может содержать себя), как это вызовет бесконечную рекурсию. Они используются для реализации n-арных матриц.
Благодарим за помощь.
FYI, хороший дизайн - это разделение проблем. Вы должны рассмотреть возможность разделения модели данных и поведения. I.e., ни «Expression», ни «Sequence» не должны иметь никаких методов, а функция «replace» должна быть реализована извне. –
Кстати, у вас есть понимание того, для чего вам нужны параметры типа? Потому что, если вы не планируете программировать на уровне, нет смысла их использовать. –
Ну, да, я использую дополнительную проверку типов для своего DSL. Тем не менее, у меня есть альтернатива кодированию различных признаков (которые я делал раньше): IntExpression, DoubleExpression и т. Д. – scand1sk