Какой смысл декларации строгости? - PullRequest
11 голосов
/ 03 июня 2011

Я запускаю Haskell и просматривал некоторые библиотеки, в которых типы данных определены с помощью "!".Пример из библиотеки bytestring:

data ByteString = PS {-# UNPACK #-} !(ForeignPtr Word8) -- payload
                     {-# UNPACK #-} !Int                -- offset
                     {-# UNPACK #-} !Int                -- length

Теперь я видел этот вопрос как объяснение того, что это значит, и я думаю, что это довольно легко понять.Но мой вопрос сейчас: какой смысл использовать это?Поскольку выражение будет оцениваться всякий раз, когда это необходимо, зачем вам начинать раннюю оценку?

Во втором ответе на этот вопрос CV Хансен говорит: «[...] иногда накладные расходы на лень могут быть слишкоммного или расточительно ".Значит ли это, что он используется для экономии памяти (сохранение значения обходится дешевле, чем сохранение выражения)?

Было бы здорово объяснить и привести пример!

Спасибо!

[ РЕДАКТИРОВАТЬ ] Я думаю, что я должен был выбрать пример без {- # UNPACK # -}.Итак, позвольте мне сделать один сам.Будет ли это когда-нибудь иметь смысл?Да, почему и в какой ситуации?

data MyType = Const1 !Int
            | Const2 !Double
            | Const3 !SomeOtherDataTypeMaybeMoreComplex

1 Ответ

13 голосов
/ 03 июня 2011

Целью здесь является не столько строгость, сколько упаковка этих элементов в структуру данных.Без строгости любой из этих трех аргументов конструктора может указывать либо на структуру значений, выделенную в куче, либо на блок отложенной оценки, выделенный в куче.Строго говоря, он может указывать только на структуру значений, выделенную кучей.При строгости и упакованных структурах эти значения можно сделать встроенными.

Поскольку каждое из этих трех значений является объектом размером с указатель и к нему в любом случае обращаются строго, что приводит к созданию строгой и упакованной структурысохраняет указатели при использовании этой структуры.

В более общем случае аннотация строгости может помочь уменьшить утечки пространства.Рассмотрим случай, подобный следующему:

data Foo = Foo Int

makeFoo :: ReallyBigDataStructure -> Foo
makeFoo x = Foo (computeSomething x)

Без аннотации строгости, если вы просто позвоните makeFoo, он создаст Foo, указывающий на ствол, указывающий на ReallyBigDataStructure, сохраняя его впамять, пока что-то не заставляет царя оценить.Если вместо этого у нас есть

data Foo = Foo !Int

Это вынуждает оценку computeSomething немедленно приступить (ну, как только что-то заставит сам makeFoo), что позволяет не оставлять ссылку на ReallyBigDataStructure.

Обратите внимание, что это другой вариант использования, чем код строки байтов;код строки байтов форсирует свои параметры довольно часто, поэтому вряд ли это приведет к утечке пространства.Вероятно, лучше всего интерпретировать код строки байтов как чистую оптимизацию, чтобы избежать разыменования указателей.

...