Does GHC removes polymorphic indirection when possible?
showInt :: Int -> String
showInt x = show x
Does the above code calls show
passing the Int
dictionary or does it calls directly the function declared on Show Int
instance?
I mean, does GHC removes polymorphic indirection from generated code when possible?
Yes. This is the generated core using GHC 7.4.2:
Foo.showInt :: GHC.Types.Int -> GHC.Base.String
[... attributes omitted ...]
Foo.showInt = GHC.Show.$fShowInt_$cshow
As you can see, it's just a direct reference to GHC.Show.$fShowInt_$cshow
.
Compare with what happens if we remove the type signature so that the inferred type Show a => a -> String
is used instead:
Foo.showInt
:: forall a_aop. GHC.Show.Show a_aop => a_aop -> GHC.Base.String
[... attributes omitted ...]
Foo.showInt =
(@ a_aot) ($dShow_aou :: GHC.Show.Show a_aot) (x_a9Z :: a_aot) ->
GHC.Show.show @ a_aot $dShow_aou x_a9Z
Here, it takes a dictionary argument $dShow_aou
and it uses the accessor function GHC.Show.show
to look up the appropriate function from this dictionary before applying the resulting function to the argument x_a9Z
.
What happens in the first case, at least conceptually, is that since the concrete type is known, GHC inserts a direct reference to the appropriate instance dictionary rather than taking it as an argument. Then, the accessor, which is basically just a record label, can be inlined and you're left with a direct reference to the appropriate function.
GHC doesn't do that. Think of a new created type for readibility:
type Vector = (Float, Float)
If GHC would removes Polymorphicism from a function like:
(!+!) :: Vector -> Vector -> Vector
(x1, y1) !+! (x2, y2) = (x1 + x2, y1 + y2)
The type would become:
(!+!) :: (Float, Float) -> (Float, Float) -> (Float, Float)
While the function is ment for Vector's specifically.
链接地址: http://www.djcxy.com/p/11508.html