Чудове запитання!
Є кілька ключових відмінностей.
Представництво
- А
newtype
гарантія , що ваші дані будуть мати точно таке ж уявлення під час виконання, як тип , який ви укладаєте.
- Поки
data
декларується абсолютно нова структура даних під час виконання.
Тож ключовим моментом тут є те, що конструкція для newtype
файлу гарантовано буде стерта під час компіляції.
Приклади:
newtype Book = Book (Int, Int)
Зауважте, як воно має точно таке ж представлення, як а (Int,Int)
, оскільки Book
конструктор стирається.
data Book = Book (Int, Int)
Має додатковий Book
конструктор, який не присутній у newtype
.
data Book = Book {-# UNPACK #-}!Int {-# UNPACK #-}!Int
Без покажчиків! Два Int
поля - це поля без коробки у Book
конструкторі.
Алгебраїчні типи даних
Через це потрібно стерти конструктор, працює newtype
лише при обгортанні типу даних одним конструктором . Не існує поняття "алгебраїчні" новітипи. Тобто ви не можете написати еквівалент нового типу, скажімо,
data Maybe a = Nothing
| Just a
оскільки він має більше одного конструктора. Також не можна писати
newtype Book = Book Int Int
Строгість
Той факт, що конструктор стирається, призводить до деяких дуже тонких відмінностей у строгості між data
і newtype
. Зокрема, data
вводиться тип, який "піднятий", тобто по суті, що він має додатковий спосіб оцінити до нижнього значення. Оскільки в процесі виконання немає додаткових конструкторів newtype
, ця властивість не втримується.
Цей додатковий вказівник у конструкторі Book
to (,)
дозволяє нам встановити нижнє значення.
Як результат, newtype
і data
мають дещо інші властивості строгості, як це пояснено у статті wiki wiki .
Розпакування
Немає сенсу розблокувати компоненти компонента newtype
, оскільки конструктора немає. Хоча писати:
data T = T {-# UNPACK #-}!Int
отримання об'єкта виконання з T
конструктором та Int#
компонентом. Ви просто отримати голий Int
з newtype
.
Список літератури :