Tak. To jest generowany przy użyciu rdzenia GHC 7.4.2:
Foo.showInt :: GHC.Types.Int -> GHC.Base.String
[... attributes omitted ...]
Foo.showInt = GHC.Show.$fShowInt_$cshow
Jak widać, to tylko bezpośrednie odniesienie do GHC.Show.$fShowInt_$cshow
.
porównania z tym, co się dzieje, gdy usuwamy podpis typu, tak aby wywnioskować typ Show a => a -> String
jest używany zamiast:
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
Tutaj zajmuje słownika argumentu $dShow_aou
i wykorzystuje funkcję dostępowej GHC.Show.show
patrzeć górę odpowiednią funkcję z tego słownika przed zastosowaniem wynikowej funkcji do argumentu x_a9Z
.
Co się dzieje w pierwszym przypadku, przynajmniej koncepcyjnie, jest to, że ponieważ znany jest konkretny typ, GHC wstawia bezpośrednie odniesienie do odpowiedniego słownika instancji, zamiast brać go za argument. Następnie, accessor, który jest w zasadzie tylko etykietą rekordu, można wstawić i pozostawiasz z bezpośrednim odniesieniem do odpowiedniej funkcji.
Często to robi, jak pokazuje hammar, a czasami nie. W związku z tym bardziej ogólne pytanie brzmi: "Jakie sytuacje uniemożliwiają GHC optymalizowanie niedowidzenia słownikowego?" . Znam pewne sytuacje związane z rozszerzeniami, ale IIRC są również takie przypadki w Haskell 98, być może z polimorficznymi funkcjami rekursywnymi. –