Разница между `data` и` newtype` в Haskell - PullRequest
176 голосов
/ 05 мая 2011

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

data Book = Book Int Int

против

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

1 Ответ

222 голосов
/ 05 мая 2011

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

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

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

  • A newtype гарантирует, что ваши данные будут иметьточно такое же представление во время выполнения, как и тип, который вы переносите.
  • Хотя data объявляет совершенно новую структуру данных во время выполнения.

Таким образом, ключевой момент здесь заключается в том, чтоКонструкция для newtype гарантированно будет стерта во время компиляции.

Примеры:

  • data Book = Book Int Int

data

  • newtype Book = Book (Int, Int)

newtype

Обратите внимание, что он имеет точно такое же представление, что и (Int,Int), поскольку конструктор Book удален.

  • data Book = Book (Int, Int)

data tuple

Имеет дополнительный конструктор Book, отсутствующий в newtype.

  • data Book = Book {-# UNPACK #-}!Int {-# UNPACK #-}!Int

enter image description here

Нет указателей!Два поля Int - это поля без размера в конструкторе Book.

Алгебраические типы данных

Из-за этого необходимо удалить конструктор, anewtype работает только при переносе типа данных с одним конструктором .Там нет понятия "алгебраических" новых типов.То есть вы не можете написать эквивалент нового типа, скажем,

data Maybe a = Nothing
             | Just a

, поскольку он имеет более одного конструктора.Вы также не можете написать

newtype Book = Book Int Int

Строгость

Тот факт, что конструктор удален, приводит к некоторым очень тонким различиям в строгости между data и newtype.В частности, data вводит тип, который «поднимается», что означает, по сути, что у него есть дополнительный способ оценки до нижнего значения.Поскольку во время выполнения нет дополнительного конструктора с newtype, это свойство не сохраняется.

Этот дополнительный указатель в конструкторе Book to (,) позволяет нам ввести нижнее значение.

В результате newtype и data имеют немного разные свойства строгости, как объяснено в вики-статье на Haskell .

Распаковка

Не имеет смысла распаковывать компоненты newtype,так как нет конструктора.В то время как вполне разумно написать:

data T = T {-# UNPACK #-}!Int

, получая объект времени выполнения с конструктором T и компонентом Int#.Вы просто получаете Int с newtype.


Ссылки :

...