Я натолкнулся на следующее определение, пытаясь изучить Haskell, используя для этого реальный проект. Я не понимаю, что означает восклицательный знак перед каждым аргументом, и мои книги, похоже, не упоминали об этом.
data MidiMessage = MidiMessage !Int !MidiMessage
haskell
syntax
lazy-evaluation
Дэвид
источник
источник
Ответы:
Это декларация строгости. По сути, это означает, что при создании значения структуры данных оно должно быть оценено как «нормальная форма слабой головы». Давайте рассмотрим пример, чтобы понять, что это значит:
Приведенная
f
выше функция при оценке вернет «thunk»: код, который нужно выполнить, чтобы выяснить его значение. На данный момент, Foo даже еще не существует, только код.Но в какой-то момент кто-то может попытаться заглянуть внутрь него, возможно, с помощью сопоставления с образцом:
Это будет выполнять достаточно кода, чтобы делать то, что ему нужно, и не более того. Таким образом, он создаст Foo с четырьмя параметрами (потому что вы не можете заглянуть внутрь него, если он не существует). Во-первых, так как мы тестируем его, нам нужно оценить весь путь туда
4
, где мы понимаем, что он не соответствует.Второе не нужно оценивать, потому что мы его не тестируем. Таким образом, вместо того,
6
чтобы храниться в этой ячейке памяти, мы просто сохраним код для возможной последующей оценки(3+3)
. Это превратится в 6, только если кто-то смотрит на это.Третий параметр, однако, имеет
!
перед ним, поэтому строго оценивается:(4+4)
выполняется и8
хранится в этой ячейке памяти.Четвертый параметр также строго оценен. Но вот где это становится немного сложнее: мы оцениваем не полностью, а только для слабой нормальной формы головы. Это означает, что мы выясняем, является ли это
Nothing
илиJust
что-то, и сохраняем это, но мы не идем дальше. Это означает, что мы храним не так,Just 10
а на самом делеJust (5+5)
, оставляя thunk внутри неоцененным. Это важно знать, хотя я думаю, что все последствия этого выходят за рамки этого вопроса.Вы можете аннотировать аргументы функции таким же образом, если вы включите
BangPatterns
расширение языка:f (1+1) (2+2)
вернет гром(1+1)*4
.источник
seq
.Простой способ увидеть разницу между строгими и нестрогими аргументами конструктора - это то, как они ведут себя, когда они не определены. Дано
Поскольку не строгий аргумент не оценивается
second
, передачаundefined
не вызывает проблемы:Но строгого аргумента быть не может
undefined
, даже если мы не используем значение:источник
!
имеет символ, а не углубляется во внутренние детали реализации.Я считаю, что это аннотация строгости.
Haskell - это чистый и ленивый функциональный язык, но иногда накладные расходы лени могут быть слишком большими или расточительными. Таким образом, чтобы справиться с этим, вы можете попросить компилятор полностью оценить аргументы функции вместо того, чтобы разбирать thunks вокруг.
На этой странице больше информации: Производительность / Строгость .
источник
map Just [1,2,3]
чтобы получить [Just 1, Just 2, Just 3]) и так далее. Я нахожу полезным подумать о способности сопоставления с образцом с ними, а также о совершенно не связанном объекте.