Haskell: рекомендации по использованию строгости

Есть ли рекомендации по использованию строгости в Haskell?

Например, я смотрел библиотеку tagsoup. Они имеют одну из своих структур данных, определенных следующим образом:

data Tag str    
    = TagOpen str [Attribute str]
    | TagClose str
    | TagText str
    | TagComment str
    | TagWarning str
    | TagPosition !Row !Column 

type Row = Int 
type Column = Int

Итак, какой именно фактор они решают, что TagPosition должен быть строгим? Есть ли рекомендации для этого?

Ответ 1

Для простых неструктурированных типов данных, таких как Int или Double, превращение их в строгие поля часто является хорошим дефолтом. Это делает их потребление пространства очень предсказуемым (и постоянным). Хотя возможно, что производительность ухудшается из-за выполнения ненужных вычислений, это, в общем, маловероятно. Например, отслеживание позиции обычно чрезвычайно просто и недорого, поэтому нечего бояться с точки зрения производительности, а предсказуемое пространственное поведение гораздо важнее.

Дополнительные преимущества строгих простых строчек заключаются в том, что их часто можно распаковать, т.е. хранить непосредственно внутри конструктора, а не через дополнительную косвенность (для него есть прагмы или флаги компилятора). Для небольших типов это обычно является преимуществом.

Для структурированных типов данных, таких как списки или деревья, ситуация намного сложнее. Простой ! редко поможет здесь, потому что это только заставляет WHNF. Оцененный список или дерево также может быть более дорогостоящим с точки зрения пространства, чем неоценимый тон. Тем не менее, иногда имеет смысл также делать такие данные строгими. В таких случаях вы обычно обертываете конструктор, используя функцию (так называемый интеллектуальный конструктор), который устанавливает инварианты строгости, вызывая deepseq в соответствующих местах.