2013-04-18 2 views
9

Ich studiere Haskell seit einiger Zeit, also bin ich ein Neuling.Haskell polymorphe Anrufe ohne vollständigen Typ Wissen

Der folgende Code ist sehr leicht verständlich:

purStrLn $ show [1] 

Hier können wir alle Arten ableiten (mit Standardeinstellungen), und alles funktioniert gut. Aber der folgende Code funktioniert auch:

putStrLn $ show [] 

auch wenn wir die Liste Typ nicht ableiten kann.

Wenn ich den Code mit GHCI ausführen erhalte ich folgendes:

Prelude> [] 
[] 
Prelude> :t it 
it :: [a] 
Prelude> 

so die Art polymorph zu sein scheint. Aber in diesem Fall würde die Show mit einem teilweise angewandten Typ aufgerufen werden.

Das gleiche Verhalten ist bei anderen Typen üblich, zum Beispiel mit Data.Map.empty, also ist es kein Listen-Feature (oder zumindest scheint es so).

Warum und wie es funktioniert?

+0

'purStrLn $ show [1]' noch auf eine Art auf dem Standard hat, als '[1] :: (Num n) => [n]' – amindfv

+0

Das stimmt, aber in solchen Fällen gibt es Standardwerte. – Totoro

+2

Beachten Sie, dass etwas anderes passiert, wenn die Typvariable unbeschränkt ist, wie z. 'length []', siehe: http://stackoverflow.com/q/7076517. – hammar

Antwort

16

Zunächst funktioniert das nur in ghci. Wenn Sie versuchen, dieses Programm zu kompilieren mit ghc finden Sie eine Art Fehlermeldung erhalten:

Test.hs:3:19: 
    Ambiguous type variable `a0' in the constraint: 
     (Show a0) arising from a use of `show' 
    Probable fix: add a type signature that fixes these type variable(s) 
    In the second argument of `($)', namely `show []' 
    In the expression: putStrLn $ show [] 
    In an equation for `main': main = putStrLn $ show [] 

eine Art Signatur Hinzufügen der Fehler gehen weg macht:

module Main where 

main = putStrLn $ show ([]::[Int]) 

Aber warum es hat in ghci arbeiten? Die Antwort lautet extended type defaulting in ghci: der Typ a ist standardmäßig () (der Einheitentyp).

Die Motivation für dieses Verhalten ist, dass es für den Benutzer ein wenig ermüdend ist, immer die Typen anzugeben, wenn er im Interpreter arbeitet. Wie Vitus stellt fest, in den Kommentaren, ghci mit -Wall lief (oder das Hinzufügen von :set -Wall zu Ihrem ~/.ghci) macht es einfacher, die säumigen zu erkennen:

<interactive>:2:12: 
    Warning: Defaulting the following constraint(s) to type `()' 
       (Show a0) arising from a use of `show' 
    In the second argument of `($)', namely `show []' 
    In a stmt of an interactive GHCi command: it <- putStrLn $ show [] 
+3

Auch das Eingeben von ': set -Wall 'in GHCi hilft, diesen Fehler zu erkennen. – Vitus

+0

Großartig, es ist eine sehr erklärende Antwort :) – Totoro