Есть ли причина не использовать INLINABLE прагма для функции?

В документации указано:

An {- # INLINABLE f # -} прагма для функции f имеет следующее поведение:

  • В то время как INLINE говорит: "Пожалуйста, включите меня", INLINABLE говорит: "Не стесняйтесь меня, используйте свое усмотрение". Другими словами, выбор остается для GHC, который использует те же правила, что и для функций без прагмы. В отличие от INLINE, это решение принимается на сайте вызова и поэтому будет зависеть от порога вложения, уровня оптимизации и т.д.

  • Как и INLINE, прагма INLINABLE сохраняет копию оригинальной RHS для встраивания целей и сохраняется в файле интерфейса независимо от размера RHS.

  • Один из способов использования INLINABLE - в сочетании со специальной встроенной функцией (раздел 7.18, "Специальные встроенные функции" ). Вызов inline f очень сильно пытается встроить f. Чтобы убедиться, что f может быть встроен, рекомендуется пометить определение f как INLINABLE, чтобы GHC гарантировал возможность разоблачения независимо от того, насколько он большой. Кроме того, аннотируя f как INLINABLE, вы гарантируете, что f оригинальная RHS встроена, а не какая-либо оптимизированная оптимизированная версия оптимизатора GHC.

  • ПРОГРАММА INLINABLE также работает со SPECIALIZE: если вы помечаете функцию f как INLINABLE, вы можете впоследствии СПЕЦИАЛИЗИРОВАТЬСЯ в другом модуле (см. раздел 7.16.8, "СПЕЦИАЛИЗАЦИЯ прагмы" ).

  • В отличие от INLINE, можно использовать INLINABLE прагму для рекурсивной функции. Основная причина заключается в том, чтобы впоследствии использовать SPECIALIZE

В чем его недостаток?

Он делает файлы интерфейса намного, намного больше? Делает ли компиляцию намного медленнее?

Есть ли какая-то причина, по которой я не должен помещать INLINABLE прагму для каждой экспортируемой функции, которую я пишу? Есть ли какая-либо причина, по которой GHC не помещает INLINABLE прагму для каждой экспортируемой функции, которую я пишу?

Ответ 1

Существуют три различия между использованием INLINABLE и отсутствием прагмы:

  • Без INLINABLE определение, которое идет в файле интерфейса, является кодом после оптимизации, тогда как с INLINABLE это код, который вы написали (более или менее). В частности, без INLINABLE, GHC может включить другие функции в определение функции.

  • Без INLINABLE, GHC опустит определение из файла интерфейса, если оно слишком велико. Если какая-то другая функция вставлена ​​в правую сторону, это может легко подтолкнуть ее к пределу.

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