I know that:
Consider the following code:
map f xs = case xs of [] -> []; (x:xs') -> f x : map f xs'
f x y = if x % 2 == 0 then y + x / 2 else y + x
main = map (f 3) [1..100]
After partial evaluating f 3
:
f3 y = if 3 % 2 == 0 then y + 3 / 2 else y + 3
main = map f3 [1..100]
And then after constant folding 3 % 2 == 0
:
f3 y = y + 3
main = map f3 [1..100]
Now let's consider inlining f
:
NOTICE: f
in f 3
will not be inlined since it is not a fully application, but we can adjust f
's definition to make it happen, for more detail, see the ghc doc here
f x = \y -> if x % 2 == 0 then y + x / 2 else y + x
main = map (\y -> if 3 % 2 == 0 then y + 3 / 2 else y + 3) [1..100]
And then after constant folding 3 % 2 == 0
:
main = map (\y -> y + 3) [1..100]
The above example shows that, both inlining and partial evaluation can provide extra optimization opportunities, but they are still very different:
f 3
in the above example) appears many times, inlining will produce very many duplicated codes.For the second point, consider the following example:
main = [f x y | x <- [1..10], y <- [1..100]]
In this case, partial evaluation can generate 10 specialized version for f x
dynamically, but inlining can do nothing.