Какая разница, когда я это пишу?
data Book = Book Int Int
против
newtype Book = Book (Int, Int) -- "Book Int Int" is syntactically invalid
haskell
types
type-systems
newtype
ewggwegw
источник
источник
newtype Book = Book Int Int
это недействительно. Однако вы можете сделать это,newtype Book = Book (Int, Int)
как указано ниже.Ответы:
Отличный вопрос!
Есть несколько ключевых отличий.
Представление
newtype
гарантирует, что ваши данные будут иметь точно такое же представление во время выполнения, что и тип, который вы переносите.data
объявляет новую структуру данных во время выполнения.Таким образом, ключевым моментом здесь является то, что конструкция для
newtype
класса гарантированно будет стерта во время компиляции.Примеры:
data Book = Book Int Int
newtype Book = Book (Int, Int)
Обратите внимание на то, что он имеет то же представление, что и a
(Int,Int)
, посколькуBook
конструктор удален.data Book = Book (Int, Int)
Имеет дополнительный
Book
конструктор, отсутствующий вnewtype
.data Book = Book {-# UNPACK #-}!Int {-# UNPACK #-}!Int
Никаких указателей! Эти два
Int
поля представляют собой распакованные поля размером со слово вBook
конструкторе.Алгебраические типы данных
Из-за необходимости стереть конструктор a
newtype
работает только при обертке типа данных с помощью одного конструктора . Нет понятия «алгебраические» новые типы. То есть вы не можете написать эквивалент newtype, скажем,data Maybe a = Nothing | Just a
поскольку у него более одного конструктора. Вы также не можете писать
newtype Book = Book Int Int
Строгость
Тот факт, что конструктор удален, приводит к очень тонким различиям в строгости между
data
иnewtype
. В частности,data
вводится «приподнятый» тип, что по сути означает, что у него есть дополнительный способ вычисления нижнего значения. Поскольку во время выполнения с нет дополнительного конструктораnewtype
, это свойство не сохраняется.Это дополнительный указатель в
Book
к(,)
конструктору позволяет поставить нижнее значение в.В результате
newtype
иdata
имеют немного другие свойства строгости, как описано в статье вики-страницы Haskell .Распаковка
Распаковывать компоненты a не имеет смысла
newtype
, так как конструктора нет. Хотя вполне разумно написать:data T = T {-# UNPACK #-}!Int
давая объект среды выполнения с
T
конструктором иInt#
компонентом. Вы просто разобралисьInt
сnewtype
.Ссылки :
источник
newtype
стирается после компиляции, а среда выполнения использует одно и то же представление для старого и нового типов, как мы можем определять экземпляры как для старого, так и для нового типа? Как среда выполнения может понять, какой экземпляр использовать?newtype
и, очевидно, еще не стираются во время компиляции .