Что означает восклицательный знак в декларации Хаскелла?
я наткнулся на следующее определение, как я пытаюсь узнать Haskell, используя реальный проект, чтобы управлять им. Я не понимаю, что означает восклицательный знак перед каждым аргументом, и мои книги, похоже, не упоминали об этом.
data MidiMessage = MidiMessage !Int !MidiMessage
3 ответа:
это декларация строгости. В принципе, это означает, что он должен быть оценен в так называемую "слабую нормальную головную форму" при создании значения структуры данных. Давайте рассмотрим пример, чтобы мы могли понять, что это значит:
data Foo = Foo Int Int !Int !(Maybe Int) f = Foo (2+2) (3+3) (4+4) (Just (5+5))
функции
f
выше, при оценке, вернет "thunk": то есть, код для выполнения, чтобы выяснить его значение. В этот момент Foo еще даже не существует, только код.но в какой-то момент кто-то может попробуйте заглянуть внутрь него, возможно, через шаблон соответствия:
case f of Foo 0 _ _ _ -> "first arg is zero" _ -> "first arge is something else"
это будет выполнить достаточно кода, чтобы сделать то, что ему нужно, и не больше. Таким образом, он создаст Foo с четырьмя параметрами (потому что вы не можете заглянуть внутрь него без его существования). Во-первых, поскольку мы тестируем его, нам нужно оценить весь путь до
4
, где мы понимаем, что это не соответствует.второй не нужно оценивать, потому что мы его не тестируем. Таким образом, вместо
6
будучи сохраненный в этом месте памяти, мы просто сохраним код для возможной последующей оценки,(3+3)
. Это превратится в 6, только если кто-то посмотрит на него.третий параметр, однако, имеет
!
перед ним, так строго оценивали:(4+4)
выполнено, и8
хранится в этой памяти.четвертый параметр также строго оценивается. Но вот где это становится немного сложнее: мы оцениваем не полностью, а только слабую нормальную форму головы. Это означает, что мы выясняем, является ли это
Nothing
илиJust
что-то, и хранить это, но мы не идем дальше. Это означает, что мы храним неJust 10
но на самом делеJust (5+5)
, оставляя удар внутри недооцененным. Это важно знать, хотя я думаю, что все последствия этого выходят за рамки этого вопроса.вы можете комментировать аргументы функции таким же образом, если вы включите
BangPatterns
язык расширение:f x !y = x*y
f (1+1) (2+2)
вернется преобразователь(1+1)*4
.
простой способ увидеть разницу между строгими и нестрогими аргументами конструктора-это то, как они ведут себя, когда они не определены. Учитывая
data Foo = Foo Int !Int first (Foo x _) = x second (Foo _ y) = y
так как нестрогий аргумент не оценивается
second
, проходящей вundefined
не вызывает проблем:> second (Foo undefined 1) 1
но строгий аргумент не может быть
undefined
, даже если мы не используем значение:> first (Foo 1 undefined) *** Exception: Prelude.undefined
Я считаю, что это строгость аннотации.
Haskell является чисто и лень функциональный язык, но иногда накладные расходы на лень может быть слишком много или расточительно. Поэтому, чтобы справиться с этим, вы можете попросить компилятор полностью оценить аргументы функции вместо разбора thunks вокруг.
там больше информации на этой странице:Производительность/Строгость.