Це декларація суворості. По суті, це означає, що при створенні значення структури даних її слід оцінювати у тому, що називається "слабкою головою нормальної форми". Давайте подивимось на приклад, щоб ми могли побачити, що це означає:
data Foo = Foo Int Int !Int !(Maybe Int)
f = Foo (2+2) (3+3) (4+4) (Just (5+5))
fВищенаведена функція , коли оцінюється, повертає "сповіщення": тобто код, який потрібно виконати, щоб з'ясувати його значення. На той момент 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.