Świetne pytanie!
Istnieje kilka kluczowych różnic.
Reprezentacja
- A
newtype
gwarantuje, że dane będą miały dokładnie taką samą reprezentację w czasie wykonywania, jak rodzaj zawinąć.
- Podczas
data
deklaruje zupełnie nową strukturę danych w czasie wykonywania.
Kluczową kwestią jest tutaj to, że konstrukcja dla newtype
gwarantowana jest wymazana w czasie kompilacji.
Przykłady:
newtype Book = Book (Int, Int)
Zauważ, że ma dokładnie taką samą reprezentację jak a (Int,Int)
, ponieważ Book
konstruktor jest kasowany.
data Book = Book (Int, Int)
Ma dodatkowy Book
konstruktor nieobecny w newtype
.
data Book = Book {-# UNPACK #-}!Int {-# UNPACK #-}!Int
Brak wskazówek! Te dwa Int
pola są w konstruktorze rozpakowanymi polami wielkości słowa Book
.
Algebraiczne typy danych
Z powodu tej potrzeby skasowania konstruktora: newtype
działa tylko podczas owijania typu danych jednym konstruktorem . Nie ma pojęcia o „typach algebraicznych”. Oznacza to, że nie można napisać nowego odpowiednika, powiedzmy,
data Maybe a = Nothing
| Just a
ponieważ ma więcej niż jednego konstruktora. Nie możesz też pisać
newtype Book = Book Int Int
Ścisłość
Usunięcie konstruktora prowadzi do bardzo subtelnych różnic w ścisłości między nimi data
i newtype
. W szczególności data
wprowadza typ, który jest „podnoszony”, co w istocie oznacza, że ma on dodatkowy sposób oceny do dolnej wartości. Ponieważ w środowisku wykonawczym nie ma dodatkowego konstruktoranewtype
, ta właściwość nie zachowuje się.
Ten dodatkowy wskaźnik w Book
(,)
konstruktorze do pozwala nam wstawić dolną wartość.
W rezultacie newtype
idata
mają nieco inne właściwości surowości, jak wyjaśniono w artykule Haskell wiki .
Rozpakowanie
Rozpakowywanie składników a nie ma sensu newtype
, ponieważ nie ma konstruktora. Chociaż napisanie:
data T = T {-# UNPACK #-}!Int
zwracanie obiektu wykonawczego za pomocą T
konstruktora i Int#
komponentu. Wystarczy dostać nagie Int
znewtype
.
Referencje :