Что означает восклицательный знак в декларации Хаскелла?
я наткнулся на следующее определение, как я пытаюсь узнать 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 вокруг.
там больше информации на этой странице:Производительность/Строгость.