Разница между data и newtype в Haskell

193

Какая разница, когда я это пишу?

data Book = Book Int Int

против

newtype Book = Book (Int, Int) -- "Book Int Int" is syntactically invalid
ewggwegw
источник
Вам следует поискать, на этот вопрос уже был дан ответ. stackoverflow.com/questions/2649305/…
tehman
Связано с stackoverflow.com/questions/2649305/…
Дон Стюарт
Также по теме: использование newtype: stackoverflow.com/questions/991467/…
Дон Стюарт
26
Обратите внимание, что newtype Book = Book Int Intэто недействительно. Однако вы можете сделать это, newtype Book = Book (Int, Int)как указано ниже.
Эдвард КМЕТТ

Ответы:

242

Отличный вопрос!

Есть несколько ключевых отличий.

Представление

  • A 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.


Ссылки :

Дон Стюарт
источник
2
Я до сих пор не думаю, что что-то пропустил бы, если бы в Haskell не было «newtype». Тонкие различия добавляют сложности к языку, которые мне не кажутся стоящими ...
martingw
15
Разница очень полезна по соображениям производительности. Поскольку конструкторы newtype стираются во время компиляции, они не налагают снижения производительности во время выполнения, которое имеет конструктор данных. Но они по-прежнему дают вам все преимущества совершенно отличного типа и любых абстракций, которые вы хотите связать с ним. Например, есть два разных способа, которыми тип данных списка может образовывать монаду. Один встроен в язык, но если вы хотите использовать другой, вам подойдет новый тип.
mightybyte
Отличное объяснение! Я не понимаю, что если newtypeстирается после компиляции, а среда выполнения использует одно и то же представление для старого и нового типов, как мы можем определять экземпляры как для старого, так и для нового типа? Как среда выполнения может понять, какой экземпляр использовать?
Константин Милютин
3
@damluar Все типы стираются во время выполнения, все они полностью разрешаются во время компиляции newtypeи, очевидно, еще не стираются во время компиляции .
точка с запятой
4
@damlaur У меня однажды был такой же вопрос, как и у вас. Когда люди говорят, что типы стираются, они не упоминают, что одна вещь НЕ стирается, а именно слово памяти, которое используется для поиска в словаре, чтобы решить, какой метод экземпляра использовать для данного фрагмента данных. Люди утверждают, что это слово не «тип», что, я думаю, зависит от вашей точки зрения, но вот и все.
Габриэль Л.