Es gibt einige Probleme, die von algebraischen Datentypen leicht gelöst werden können. Beispielsweise kann ein Listentyp sehr prägnant ausgedrückt werden als:
data ConsList a = Empty | ConsCell a (ConsList a)
consmap f Empty = Empty
consmap f (ConsCell a b) = ConsCell (f a) (consmap f b)
l = ConsCell 1 (ConsCell 2 (ConsCell 3 Empty))
consmap (+1) l
Dieses spezielle Beispiel ist in Haskell enthalten, es ist jedoch in anderen Sprachen ähnlich, da die Unterstützung für algebraische Datentypen nativ ist.
Es stellt sich heraus, dass es eine offensichtliche Zuordnung zur Subtypisierung im OO-Stil gibt: Der Datentyp wird zu einer abstrakten Basisklasse und jeder Datenkonstruktor wird zu einer konkreten Subklasse. Hier ist ein Beispiel in Scala:
sealed abstract class ConsList[+T] {
def map[U](f: T => U): ConsList[U]
}
object Empty extends ConsList[Nothing] {
override def map[U](f: Nothing => U) = this
}
final class ConsCell[T](first: T, rest: ConsList[T]) extends ConsList[T] {
override def map[U](f: T => U) = new ConsCell(f(first), rest.map(f))
}
val l = (new ConsCell(1, new ConsCell(2, new ConsCell(3, Empty)))
l.map(1+)
Das einzige, was über die naive Unterklasse hinaus benötigt wird, ist eine Methode zum Versiegeln von Klassen, dh eine Methode, die das Hinzufügen von Unterklassen zu einer Hierarchie unmöglich macht.
Wie würden Sie dieses Problem in einer Sprache wie C # oder Java angehen? Die beiden Stolpersteine, die ich bei der Verwendung algebraischer Datentypen in C # gefunden habe, waren:
- Ich konnte nicht herausfinden, wie der unterste Typ in C # heißt (dh ich konnte nicht herausfinden, in was ich ihn einfügen soll
class Empty : ConsList< ??? >
) - Ich konnte keine Methode zum Versiegeln finden,
ConsList
sodass der Hierarchie keine Unterklassen hinzugefügt werden können
Was wäre der idiomatischste Weg, um algebraische Datentypen in C # und / oder Java zu implementieren? Oder, wenn es nicht möglich ist, was wäre der idiomatische Ersatz?