Было бы довольно шокирующим, если бы GH C "заметил" дублированный аргумент и исключил его для вас. Такой анализ глазков технически невозможен, но зачастую он обходится вам гораздо дороже, чем выгода. Представьте, что у вас есть
g x = f x + f 6
Если компилятор хочет избежать лишних вызовов на f
, он может каждый раз проверять, является ли x == 6
, и если да, то делиться результатом. Но большую часть времени x /= 6
, и поэтому эта дополнительная проверка стоит вашего времени. Если вы думаете, что оптимизация будет срабатывать достаточно часто, чтобы быть полезной, вы, конечно, можете сделать это самостоятельно.
Я также посмотрел на вывод -ddump-simpl
, чтобы увидеть ядро, которое создает GHCI. Я полагаю, что это вывод после того, как все шаги оптимизации были выполнены, таким образом, это был бы окончательный ответ, что, по крайней мере в GHCI, эта оптимизация не выполняется; однако я не уверен в этом.
Обратите внимание, что здесь есть два безусловных вызова f
.
$ ghci -ddump-simpl
...
Prelude> f (2 * 3) + f 6
==================== Simplified expression ====================
let {
it_a2Cx :: forall a. (GHC.Num.Num a, GHC.Classes.Ord a) => a
[LclId,
Arity=2,
Unf=Unf{Src=<vanilla>, TopLvl=False, Value=True, ConLike=True,
WorkFree=True, Expandable=True, Guidance=IF_ARGS [150 0] 550 0}]
it_a2Cx
= \ (@ a_a2Yl)
($dNum_a2YF :: GHC.Num.Num a_a2Yl)
($dOrd_a2YG :: GHC.Classes.Ord a_a2Yl) ->
GHC.Num.+
@ a_a2Yl
$dNum_a2YF
(Ghci1.f
@ a_a2Yl
$dOrd_a2YG
$dNum_a2YF
(GHC.Num.*
@ a_a2Yl
$dNum_a2YF
(GHC.Num.fromInteger @ a_a2Yl $dNum_a2YF 2)
(GHC.Num.fromInteger @ a_a2Yl $dNum_a2YF 3)))
(Ghci1.f
@ a_a2Yl
$dOrd_a2YG
$dNum_a2YF
(GHC.Num.fromInteger @ a_a2Yl $dNum_a2YF 6)) } in
GHC.Base.thenIO
@ ()
@ [()]
(System.IO.print
@ GHC.Integer.Type.Integer
GHC.Show.$fShowInteger
(it_a2Cx
@ GHC.Integer.Type.Integer
GHC.Num.$fNumInteger
GHC.Integer.Type.$fOrdInteger))
(GHC.Base.returnIO
@ [()]
(GHC.Types.:
@ ()
(it_a2Cx
`cast` (UnsafeCo representational (forall a.
(GHC.Num.Num a, GHC.Classes.Ord a) =>
a) ()
:: (forall a. (GHC.Num.Num a, GHC.Classes.Ord a) => a :: *)
~R# (() :: *)))
(GHC.Types.[] @ ())))
12