2012-11-30 9 views
7
showInt :: Int -> String 
showInt x = show x 

Czy powyższy kod wywołuje show przechodzącej słownika Int lub nie wywołuje bezpośrednio funkcja zadeklarowana na Show Int przykład?Czy GHC usuwa polimorficzny efekt pośredni, jeśli to możliwe?

Mam na myśli, czy GHC usuwa polimorficzny kierunek z wygenerowanego kodu, gdy jest to możliwe?

+2

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. –

Odpowiedz

10

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.

-7

GHC tego nie robi. Pomyśl o nowo utworzonego typu dla czytelności:

type Vector = (Float, Float) 

Jeśli GHC byłoby usuwa Polymorphicism z funkcji takich jak:

(!+!) :: Vector -> Vector -> Vector 
(x1, y1) !+! (x2, y2) = (x1 + x2, y1 + y2) 

typu staną:

(!+!) :: (Float, Float) -> (Float, Float) -> (Float, Float) 

Gdy funkcja jest ment w szczególności dla Vector.

+5

Deklaracja 'typ Vector = (Float, Float)' oznacza, że ​​typ 'Vector' i typ' (Float, Float) 'są dokładnie takie same, a twoja funkcja ma zarówno typ" Wektor -> Wektor -> Wektor 'i typ' (Float, Float) -> (Float, Float) -> (Float, Float) 'ponieważ oznaczają to samo, więc nie, to nie jest poprawne. – AndrewC

+3

Podczas generowania kodu GHC specjalizuje się w funkcjach polimorficznych tam, gdzie to możliwe, generując bardziej wydajne wersje znanych typów. Inlining może być również użyty do rozwiązania pośredniego. –