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

上一篇: 如何在backbone.js中保存模型集合?

下一篇: GHC在可能的情况下是否消除多态性间接性?