Es scheint, dass jede Bounded-Instanz eine vernünftige Implementierung von Enum haben sollte. Ich kann mir kein Gegenbeispiel vorstellen, obwohl ich verstehen werde, warum dies nicht der Fall ist, wenn jemand eines findet, das nicht pathologisch ist.
Ausgehend :i
von den beiden Typklassen scheint die einzige Ausnahme, die derzeit in der Standardbibliothek enthalten ist, Tupel zu sein, die begrenzt, aber keine Aufzählungen sind. Jedes Bounded-Tupel muss jedoch auch auf vernünftige Weise aufzählbar sein, indem einfach das letzte Element inkrementiert und dann umbrochen wird, wenn es zu maxBound gelangt.
Diese Änderung würde wahrscheinlich auch das Hinzufügen predB
und / nextB
oder ähnliches zu Bounded beinhalten, um einen sicheren / schleifenförmigen Weg zum Durchlaufen der Enum-Werte zu finden. In diesem Fall toEnum 0 :: (...)
wäre gleich(toEnum 0, toEnum 0, ...) :: (...)
Double
/Float
und alle ähnlichen Typen implementieren sieEnum
trotzdem, sie machen nursucc = (+ 1)
undfromEnum = truncate
. Haskells Weg ist aus praktischer Sicht tatsächlich sinnvoll, da sonst [0, 0,5 ..] und ähnliches nicht funktionieren würden. Haskell scheint sich also keine Sorgen um die Zählbarkeit zu machen, wenn es um Enums geht.succ
ist(+1)
. Das ist seltsam, weilDouble
undFloat
haben nicht unendliche Präzision und sind daher aufzählbar -succ
hätte als +1 ULP definiert werden können .Antworten:
Ein praktisches Beispiel, das mir gefällt, stammt aus der Welt der Programmiersprachen: Die Menge der Typen in einem OO-System ist begrenzt und diskret, aber nicht aufzählbar und teilweise geordnet, aber nicht vollständig geordnet.
Die fragliche Teilreihenfolge ist die Subtypisierungsbeziehung
<:
. Die Obergrenze wäre dann der obere Typ (den C #object
und Scala aufruftAny
), und die Untergrenze wäre der untere Typ (ScalaNothing
; C # / Java haben kein nennenswertes Äquivalent).Es gibt jedoch keine Möglichkeit, alle Typen im Typsystem aufzulisten, sodass Sie keine schreiben können
instance Enum Type
. Dies sollte klar sein: Benutzer können ihre eigenen Typen schreiben, sodass sie nicht im Voraus wissen können, was sie sein werden. Sie können alle Typen in einem bestimmten Programm auflisten, jedoch nicht im gesamten System.Ebenso ist (gemäß einer bestimmten vernünftigen Definition der Subtypisierung)
<:
reflexiv, transitiv und antisymmetrisch, aber nicht vollständig . Es gibt Typenpaare, die nicht mit verwandt sind<:
. (Cat
undDog
sind beide Subtypen vonAnimal
, aber keiner ist ein Subtyp des anderen.)Angenommen, wir schreiben einen Compiler für eine einfache OO-Sprache. Hier ist die Darstellung der Typen in unserem System:
Und die Definition der Subtypisierungsrelation:
Dies gibt uns auch eine Supertypisierungsbeziehung.
Sie können auch die kleinste Obergrenze von zwei Typen finden:
Übung: Zeigen Sie, dass
Type
ein begrenzter vollständiger Poset auf zwei Arten gebildet wird, unter<:
und unter>:
.quelle
x == y = x <= y && y <= x
. Wenn ich einePoset
Klasse entwerfen würde, hätte ichclass Eq a => Poset a
. Ein schnelles Google bestätigt, dass andere Leute die gleiche Idee hatten .data Bound a = Min | Val a | Max
welche Augments ein Typa
mit+∞
und-∞
Elementen enthält. Durch KonstruktionBound a
kann immer eine Instanz von gemacht werden,Bounded
aber es wäre nur gleichwertig, wenn der zugrunde liegende Typa
istDouble
, wobeiconst (1/0)
ismaxBound
undconst (negate 1/0)
isminBound
but\x -> 1 - x
und\x -> x - 1
unvergleichbar sind.Dies liegt daran, dass die Vorgänge unabhängig sind. Wenn Sie sie also mit einer Unterklassenbeziehung verknüpfen, erhalten Sie eigentlich nichts. Angenommen, Sie wollten einen benutzerdefinierten Typ erstellen, der implementiert wurde
Bounded
, möglicherweiseDoubles
zwischen max und min, aber Sie mussten keine derEnum
Operationen ausführen. WennBounded
es sich um eine Unterklasse handeln würde, müssten Sie ohnehin alleEnum
Funktionen implementieren , um sie zum Kompilieren zu bringen.Es spielt keine Rolle, ob es eine vernünftige Implementierung für
Enum
oder eine andere Anzahl von Typklassen gibt. Wenn Sie es nicht wirklich benötigen, sollten Sie nicht gezwungen sein, es zu implementieren.Vergleichen Sie dies mit sagen,
Ord
undEq
. Dort sind dieOrd
Operationen von denen abhängigEq
, daher ist es sinnvoll, die Unterklasse zu fordern, um Doppelarbeit zu vermeiden und Konsistenz zu gewährleisten.quelle
Bounded
"Ord ist keine Superklasse von Bounded, da Typen, die nicht vollständig geordnet sind, auch Ober- und Untergrenzen haben können."<:
für ist ein Subtyp von ,∀ T S. T <: S ∨ S <: T
gilt nicht (zBint !<: bool ∧ bool !<: int
). Sie würden wahrscheinlich darauf stoßen, wenn Sie einen Compiler schreiben würden.