Jaka jest różnica, kiedy to piszę?
data Book = Book Int Int
przeciw
newtype Book = Book (Int, Int) -- "Book Int Int" is syntactically invalid
haskell
types
type-systems
newtype
ewggwegw
źródło
źródło
newtype Book = Book Int Int
to nie jest poprawne. Możesz jednak mieć,newtype Book = Book (Int, Int)
jak zauważyli donowie poniżej.Odpowiedzi:
Świetne pytanie!
Istnieje kilka kluczowych różnic.
Reprezentacja
newtype
gwarantuje, że dane będą miały dokładnie taką samą reprezentację w czasie wykonywania, jak rodzaj zawinąć.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:
data Book = Book Int Int
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 wnewtype
.data Book = Book {-# UNPACK #-}!Int {-# UNPACK #-}!Int
Brak wskazówek! Te dwa
Int
pola są w konstruktorze rozpakowanymi polami wielkości słowaBook
.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,ponieważ ma więcej niż jednego konstruktora. Nie możesz też pisać
Ścisłość
Usunięcie konstruktora prowadzi do bardzo subtelnych różnic w ścisłości między nimi
data
inewtype
. W szczególnościdata
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:zwracanie obiektu wykonawczego za pomocą
T
konstruktora iInt#
komponentu. Wystarczy dostać nagieInt
znewtype
.Referencje :
źródło
newtype
jest usuwany po kompilacji, a środowisko wykonawcze używa tej samej reprezentacji dla starych i nowych typów, w jaki sposób możemy nadal być w stanie zdefiniować wystąpienia zarówno dla starego, jak i nowego typu? Jak środowisko wykonawcze może zrozumieć, której instancji użyć?newtype
oczywiście nie są jeszcze kasowane.