Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 678
Thiago Negri Avatar asked Nov 30 '12 16:11

Thiago Negri


1 Answers

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.

like image 58
hammar Avatar answered Dec 09 '22 18:12

hammar