Частичная оценка правых секций оператора
У меня есть функция (*~)
. Большая часть стоимости оценки x *~ y
исходит из проверки второго аргумента, примерно по этим строкам:
(*~) :: a -> b d -> c d a
x *~ y = case y' of
Bar -> cheapFunction y' x
Baz -> cheapFunction2 y' x
Quux -> cheapFunction3 y' x
where
y' = expensive y
Есть ли какой-то способ убедить GHC частично оценить разделы оператора, такие как (*~ y)
?
Я попробовал переписать его так:
(*~) = flip go
where
go y = let y' = expensive y
in case y' of
Bar -> cheapFunction y'
Baz -> cheapFunction2 y'
Quux -> cheapFunction3 y'
но, похоже, это не помогло. Я думаю, это может быть из-за того, что flip
требует всех аргументов, прежде чем он перевернет?
Один из способов - просто перевернуть сам оператор, но он читается гораздо более естественным образом, когда дорогой операнд находится с правой стороны, потому что он совпадает с существующей нотной записью.
Может ли правильно созданная {-# RULE #-}
выручить меня здесь? Если да, то что сказать? (Я не знаю, как далеко синтаксис секционирования будет снят, прежде чем правила будут искать совпадения, между прочим.)
Ответы
Ответ 1
Чтобы вызвать такую оптимизацию, вам нужно убедиться, что ваша функция встроена. Поместите прагму {-# INLINE (*~) #-}
перед объявлением функции (*~)
. Я не могу гарантировать, что он решит вашу проблему, но это единственный способ, с которым я обращаюсь к нему. После этого я проверил созданный код ядра с помощью инструмента ghc-core.
Однако ваша проблема на самом деле является лишь признаком неправильной составы кода. Ваша функция выполняет множество несвязанных вещей. expensive y
следует просто исключить из него, тогда ваша проблема будет стерта как таковая. I.e, шаблон использования должен быть x *~ expensive y
вместо x *~ y
.