Karls Antwort ist gut. Hier ist eine zusätzliche Verwendung, von der ich glaube, dass sie noch niemand erwähnt hat. Die Art von
if E then A else B
sollte ein Typ sein, der alle Werte im Typ von Aund alle Werte im Typ von enthält B. Wenn der Typ von Bist Nothing, kann der Typ des ifAusdrucks der Typ von sein A. Ich werde oft eine Routine erklären
def unreachable( s:String ) : Nothing = throw new AssertionError("Unreachable "+s)
zu sagen, dass der Code voraussichtlich nicht erreicht wird. Da es sich um den Typ handelt Nothing, unreachable(s)kann es jetzt in jedem ifoder (häufiger) verwendet werden, switchohne dass die Art des Ergebnisses beeinflusst wird. Zum Beispiel
val colour : Colour := switch state of
BLACK_TO_MOVE: BLACK
WHITE_TO_MOVE: WHITE
default: unreachable("Bad state")
Scala hat so einen Nichts-Typ.
Ein weiterer Anwendungsfall für Nothing(wie in Karls Antwort erwähnt) ist List [Nothing]. Dabei handelt es sich um die Art von Listen, deren Mitglieder jeweils den Typ Nothing haben. Es kann also der Typ der leeren Liste sein.
Die Schlüsseleigenschaft Nothing, die diese Anwendungsfälle funktionieren lässt, ist nicht, dass sie keine Werte haben - obwohl sie beispielsweise in Scala keine Werte haben -, dass sie ein Untertyp jedes anderen Typs sind.
Angenommen, Sie haben eine Sprache, in der jeder Typ denselben Wert enthält - nennen wir es (). In einer solchen Sprache kann der Einheitentyp, der ()den einzigen Wert hat, ein Untertyp jedes Typs sein. Das macht es nicht zu einem Bottom-Typ im Sinne des OP; Dem OP war klar, dass ein Bottom-Typ keine Werte enthält. Da es sich jedoch um einen Typ handelt, der ein Untertyp jedes Typs ist, kann er in etwa die gleiche Rolle spielen wie ein unterer Typ.
Haskell macht die Dinge ein bisschen anders. In Haskell kann ein Ausdruck, der niemals einen Wert erzeugt, das Typschema haben forall a.a. Eine Instanz dieses Typschemas wird mit jedem anderen Typ vereinheitlicht, sodass sie effektiv als unterer Typ fungiert, obwohl (Standard-) Haskell keine Vorstellung von Untertypisierung hat. Beispielsweise hat die errorFunktion aus dem Standardvorspiel ein Typschema forall a. [Char] -> a. Du kannst also schreiben
if E then A else error ""
und der Typ des Ausdrucks Aist für jeden Ausdruck der gleiche wie der Typ von A.
Die leere Liste in Haskell hat das Typschema forall a. [a]. Wenn Aein Ausdruck ist, dessen Typ ein Listentyp ist, dann
if E then A else []
ist ein Ausdruck mit dem gleichen Typ wie A.
voidDaten explizit definieren ...