Gute Frage!
Es gibt mehrere wesentliche Unterschiede.
Darstellung
- A
newtype
garantiert, dass Ihre Daten zur Laufzeit genau dieselbe Darstellung haben wie der Typ, den Sie umbrechen.
- Während
data
deklariert zur Laufzeit eine brandneue Datenstruktur.
Der entscheidende Punkt hierbei ist also, dass das Konstrukt für das newtype
beim Kompilieren garantiert gelöscht wird.
Beispiele:
newtype Book = Book (Int, Int)
Beachten Sie, dass es genau die gleiche Darstellung wie a hat (Int,Int)
, da der Book
Konstruktor gelöscht wird.
data Book = Book (Int, Int)
Hat einen zusätzlichen Book
Konstruktor nicht in der newtype
.
data Book = Book {-# UNPACK #-}!Int {-# UNPACK #-}!Int
Keine Hinweise! Die beiden Int
Felder sind wortgroße Felder im Book
Konstruktor.
Algebraische Datentypen
Aufgrund dieser Notwendigkeit, den Konstruktor zu löschen, newtype
funktioniert a nur, wenn ein Datentyp mit einem einzelnen Konstruktor umbrochen wird . Es gibt keine Vorstellung von "algebraischen" neuen Typen. Das heißt, Sie können kein Newtype-Äquivalent von beispielsweise schreiben.
data Maybe a = Nothing
| Just a
da es mehr als einen Konstruktor hat. Du kannst auch nicht schreiben
newtype Book = Book Int Int
Strenge
Die Tatsache, dass der Konstruktor gelöscht wird, führt zu einigen sehr subtilen Unterschieden in der Strenge zwischen data
und newtype
. Insbesondere wird data
ein Typ eingeführt, der "angehoben" wird, was im Wesentlichen bedeutet, dass er eine zusätzliche Möglichkeit bietet, einen unteren Wert zu ermitteln. Da es zur Laufzeit mit keinen zusätzlichen Konstruktor gibt newtype
, gilt diese Eigenschaft nicht.
Mit diesem zusätzlichen Zeiger im Book
to- (,)
Konstruktor können wir einen unteren Wert eingeben.
Infolgedessen newtype
und data
haben leicht unterschiedliche Strengeigenschaften, wie im Haskell-Wiki-Artikel erläutert .
Unboxing
Es ist nicht sinnvoll, die Komponenten von a zu entpacken newtype
, da es keinen Konstruktor gibt. Während es völlig vernünftig ist zu schreiben:
data T = T {-# UNPACK #-}!Int
Ausgeben eines Laufzeitobjekts mit einem T
Konstruktor und einer Int#
Komponente. Sie bekommen nur eine nackte Int
mit newtype
.
Referenzen :