Что делает?() В конструкторе данных?

Я читаю исходный код Data.Map, и я обнаружил, что!() используется в конструкторе данных data Map k a.

data Map k a  = Tip 
              | Bin {-# UNPACK #-} !Size !k a !(Map k a) !(Map k a) 

Я нахожу, что !( ) не влияет на то, как сопоставление patten с данными. В функции mapWithKey совпадение patten все еще существует для 5 вещей. Поэтому я не считаю это оператором.

mapWithKey f (Bin sx kx x l r) 

После googleing я обнаружил, что !( ) может быть связан с -XBangPatterns, который используется для ленивой оценки. Я прав? Или это для других целей?

Ответ 1

! в объявлениях типов данных используется для указания строгости. Если мы ищем его в Hoogle, мы видим ссылку на ключевое слово!., что объясняет поведение. Отчет определяет точное поведение.

В data Foo = Foo ... !T ... конструктор Foo заставляет свой аргумент, т.е. Foo ... x ... = x `seq` RealFoo ... x .... где RealFoo - конструктор, который вы получите без !.

{-# UNPACK #-} является расширением GHC, что означает, что Size (т.е. Int) сохраняется в незапаложенном виде непосредственно как часть типа данных.

Ответ 2

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

высокопроизводительные слайды Haskell охватывают это более подробно.