Reduzieren verschachtelter Listen desselben Typs

Angenommen, ich möchte verschachtelte Listen desselben Typs reduzieren ... Zum Beispiel

<code>    ListA(Element(A), Element(B), ListA(Element(C), Element(D)), ListB(Element(E),Element(F)))
</code>

ListA enthält verschachtelte Liste desselben Typs (ListA(Element(C), Element(D))Ich möchte es also durch die Werte ersetzen, die es enthält. Das Ergebnis des oberen Beispiels sollte also so aussehen:

<code>ListA(Element(A), Element(B), Element(C), Element(D), ListB(Element(E),Element(F)))
</code>

Aktuelle Klassenhierarchie:

<code>abstract class SpecialList() extends Exp {
    val elements: List[Exp]
}

case class Element(name: String) extends Exp

case class ListA(elements: List[Exp]) extends SpecialList {
        override def toString(): String = "ListA("+elements.mkString(",")+")"
}

case class ListB(elements: List[Exp]) extends SpecialList {
        override def toString(): String = "ListB("+elements.mkString(",")+")"
}

object ListA{def apply(elements: Exp*):ListA = ListA(elements.toList)}
object ListB{def apply(elements: Exp*):ListB = ListB(elements.toList)}
</code>

Ich habe drei Lösungen gefunden, die funktionieren, aber ich denke, es muss einen besseren Weg geben, um dies zu erreichen:

Erste Lösung:

<code>def flatten[T <: SpecialList](parentList: T): List[Exp] = {
        val buf = new ListBuffer[Exp]

        for (feature <- parentList.elements) feature match {
            case listA:ListA if parentList.isInstanceOf[ListA] => buf ++= listA.elements
            case listB:ListB if parentList.isInstanceOf[ListB] => buf ++= listB.elements
            case _ => buf += feature
        }
        buf.toList
    }
</code>

Zweite Lösung:

<code>def flatten[T <: SpecialList](parentList: T): List[Exp] = {
    val buf = new ListBuffer[Exp]

    parentList match {
        case listA:ListA => for (elem <- listA.elements) elem match {
                                case listOfTypeA:ListA => buf ++= listOfTypeA.elements
                                case _ => buf += elem
                            }

        case listB:ListB => for (elem <- listB.elements) elem match {
                                case listOfTypeB:ListB => buf ++= listOfTypeB.elements
                                case _ => buf += elem
                            }
    }

    buf.toList
}
</code>

Dritte Lösung

<code>def flatten[T <: SpecialList](parentList: T): List[Exp] = parentList.elements flatMap {
    case listA:ListA if parentList.isInstanceOf[ListA] => listA.elements
    case listB:ListB if parentList.isInstanceOf[ListB] => listB.elements
    case other => List(other)
}
</code>

Meine Frage ist, ob es eine bessere, allgemeinere Möglichkeit gibt, die gleiche Funktionalität wie in allen drei oberen Lösungen zu erzielen, bei denen der Code wiederholt wird.

Antworten auf die Frage(3)

Ihre Antwort auf die Frage