Оптимизация постоянной функции

Если у меня есть функция fun типа:

-- For example, `SomeRecord` can have more than 2 fields,
-- but 20 or 30
data SomeRecord a b = SomeRecord {
  f1 :: a -> b,
  f2 :: a -> b -> Bool
}

fun :: SomeRecord Int Bool
fun = SomeRecord ...

и затем я вызываю fun в разных местах моей программы, будет ли код, созданный GHC, вызывать fun каждый раз или он будет заменен некоторой «ссылкой» на результат этой нулевой (фактически постоянной) функции, как компиляторы C делают это с константами? Что-то вроде «вызовите его в первый раз, а затем замените этим значением везде, на любой глубине вложенности» (или GHC мог бы сделать это даже без вызова), возможно ли это? Нужны ли мне для этого какие-то специальные флаги компилятора (сейчас я использую только -O2)?

В GHC fun будет оцениваться только один раз, а f1 fun someInt будет оцениваться один раз за вызов. Я не уверен в том, чего вы здесь ожидаете. Кроме того, вы можете поэкспериментировать с Debug.Trace.trace, чтобы увидеть, что и когда оценивается (даже если это может измениться в зависимости от оптимизации).

chi 01.08.2024 13:22
fun вообще не является функцией. Это просто значение типа SomeRecord Int Bool. Думаю, из-за лени можно было бы спросить, «вызывается» ли SomeRecord несколько раз, один раз за использование fun.
chepner 01.08.2024 16:04

Я понимаю лень, я не понимаю, где сохраняются эти thunks/values: какие-то вложенные контексты? Глобальное значение - может быть, кэшировано в глобальном пространстве имен... а как насчет модулей? ChatGPT говорит, что в GHC существует «совместное использование» и он разделяет значения, но из-за прозрачности ссылок я ожидаю, что даже локальные/вложенные «константы» будут «совместно использоваться» (оцениваются один раз), но я не уверен.

RandomB 01.08.2024 17:21

@RandomB В первом приближении, если вы определяете имя в некоторой области, то каждый раз, когда вы ссылаетесь на одно и то же имя в той же области, это просто ссылка на одно общее значение. Таким образом, если вы определяете имя в глобальной области (с определением верхнего уровня, например fun), тогда существует одно значение, которое используется всеми ссылками (и импорт определений верхнего уровня из других модулей считается одной и той же глобальной областью времени выполнения для эту цель). Это не является жесткой гарантией, поскольку компилятор может «отделить» ресурсы для оптимизации, но оптимизация предназначена для этого; он старается не усугублять ситуацию.

Ben 02.08.2024 05:40
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В GHC fun скомпилируется в объект, который при первом вычислении перезаписывает себя вычисленным значением. Это произойдет даже без каких-либо оптимизаций. (Действительно, отключить это поведение — трудная задача, а не включить его.)

Другие вопросы по теме