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


193

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

data Book = Book Int Int

против

newtype Book = Book (Int, Int) -- "Book Int Int" is syntactically invalid

Вам следует поискать, на этот вопрос уже был дан ответ. stackoverflow.com/questions/2649305/…
— tehman


Также по теме: использование 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 У меня однажды был такой же вопрос, как и у вас. Когда люди говорят, что типы стираются, они не упоминают, что одна вещь НЕ стирается, а именно слово памяти, которое используется для поиска в словаре, чтобы решить, какой метод экземпляра использовать для данного фрагмента данных. Люди утверждают, что это слово не «тип», что, я думаю, зависит от вашей точки зрения, но вот и все.
— Габриэль Л.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.