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

Ist der obige Code ruft show das Int Wörterbuch vorbei oder nicht nennt es direkt die Funktion auf Show Int Instanz erklärt?Entfernt GHC polymorphe Indirektion wenn möglich?

Ich meine, entfernt GHC polymorphe Indirektion von generiertem Code, wenn möglich?

+2

Es wird oft tun, wie von hammar gezeigt, und manchmal nicht. Daher ist die allgemeinere Frage: "Welche Situationen verhindern, dass GHC die sprachliche Indirektion umgeht?" . Ich kenne einige Situationen mit Erweiterungen, aber IIRC gibt es auch solche Fälle in Haskell 98, vielleicht mit polymorphen rekursiven Funktionen. –

Antwort

10

Ja. Dies ist der erzeugte Kern GHC mit 7.4.2:

Foo.showInt :: GHC.Types.Int -> GHC.Base.String 
[... attributes omitted ...] 
Foo.showInt = GHC.Show.$fShowInt_$cshow 

Wie Sie sehen, es ist nur ein direkter Bezug auf GHC.Show.$fShowInt_$cshow.

vergleichen mit dem, was passiert, wenn wir die Art Signatur entfernen, so dass der abgeleitete Typ Show a => a -> String stattdessen verwendet wird:

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 

Hier braucht es ein Wörterbuch Argument $dShow_aou und verwendet die Zugriffsfunktion GHC.Show.show nachschlagen die entsprechende Funktion aus diesem Wörterbuch vor dem Anwenden der resultierenden Funktion auf das Argument x_a9Z. Im ersten Fall, zumindest konzeptionell, ist es so: Da der konkrete Typ bekannt ist, fügt GHC einen direkten Verweis auf das entsprechende Instanzwörterbuch ein, anstatt es als Argument zu verwenden. Dann kann der Accessor, der im Grunde nur ein Plattenlabel ist, inline sein, und Sie haben mit einem direkten Verweis auf die entsprechende Funktion.

-7

GHC macht das nicht. Denken Sie an einen neu erstellten Typ für bessere Lesbarkeit:

type Vector = (Float, Float) 

Wenn GHC Polymorphicism aus einer Funktion wie beseitigt würden:

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

Während die Funktion ment ist:

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

Der Typ würde speziell für Vector.

+5

Die Deklaration 'type Vector = (Float, Float)' bedeutet, dass der Typ 'Vector' und der Typ' (Float, Float) genau gleich sind und Ihre Funktion den Typ 'Vector -> Vector -> Vector hat 'und der Typ' (Float, Float) -> (Float, Float) -> (Float, Float) 'weil sie dasselbe bedeuten, also nein, das stimmt nicht. – AndrewC

+3

Beim Generieren von Code spezialisiert sich GHC soweit wie möglich auf polymorphe Funktionen und erzeugt bei bekannten Typen effizientere Versionen. Inlining kann auch verwendet werden, um die Indirektion aufzulösen. –