Ответ 1
(Следующее относится к GHC, другие компиляторы могут использовать разные соглашения о хранении)
Правило большого пальца: конструктор стоит одно слово для заголовка и одно слово для каждого поля. Исключение: конструктор без полей (например, Nothing
или True
) не занимает места, потому что GHC создает один экземпляр этих конструкторов и разделяет его среди всех применений.
Слово представляет собой 4 байта на 32-битной машине и 8 байтов на 64-разрядной машине.
Так, например,
data Uno = Uno a
data Due = Due a b
a Uno
принимает 2 слова, a Due
принимает 3.
Тип Int
определяется как
data Int = I# Int#
теперь Int#
берет одно слово, поэтому Int
занимает всего 2. Большинство распакованных типов принимают одно слово, исключения - Int64#
, Word64#
и Double#
(на 32-разрядной машине), которые принимают 2. GHC на самом деле имеет кэш небольших значений типа Int
и Char
, поэтому во многих случаях они не занимают кучи. A String
требуется только пространство для ячеек списка, если вы не используете Char
> 255.
An Int8
имеет идентичное представление Int
. Integer
определяется следующим образом:
data Integer
= S# Int# -- small integers
| J# Int# ByteArray# -- large integers
поэтому маленький Integer
(S#
) принимает 2 слова, но большое целое число принимает переменное количество пространства в зависимости от его значения. A ByteArray#
принимает 2 слова (заголовок + размер) плюс пространство для самого массива.
Обратите внимание, что конструктор, определенный с помощью newtype
, свободен. newtype
- это просто идея времени компиляции, и она не занимает места и не требует инструкций во время выполнения.
Подробнее в Макет кучных объектов в комментарии GHC.