2013-07-08 10 views
8

Ich untersuche, wie mächtig Funktion Überladung in GHC ist. Ich habe den folgenden Code geschrieben:Warum ist diese Art Anmerkung in Haskell notwendig?

class F_third_arg a where 
    run_f :: (Integer, a) -> Integer 

instance F_third_arg Integer where 
    run_f (_, x) = x 

instance F_third_arg String where 
    run_f (x, _) = x 

my_fun :: (F_third_arg a) => Integer -> (a -> Integer) 
my_fun x = \a -> run_f(x, a) 

main :: IO() 
main = putStrLn $ show(((my_fun::Integer->(Integer->Integer)) 5) $ 6) 

(ja, ich brauche -XTypeSynonymInstances -XFlexibleInstances) und ich war überrascht, dass die Compiler die Typanmerkung in der Nähe von dem Aufruf von my_fun muss. Es wird auf zwei Zahlen angewendet - was ist das Problem mit dieser Annotation? Wie lauten die Überladungsregeln für diese beiden Erweiterungen?

+0

'FlexibleInstances' bedeutet bereits' TypeSynonymInstances'. 'PutStrLn. show' entspricht "print". Und Sie können ziemlich viele Parens weglassen ... – leftaroundabout

+3

Wie für den Typ ** defaulting ** (natürlich kann der Compiler nicht _infer_ der Typ: numerische Literale sind polymorph!), Ich bin kein Experte dafür, aber GHC erweiterte Standardregeln tun den Job ('{- # LANGUAGE ExtendedDefaultRules # -}' oder GHCi). Ein besserer Weg wäre 'print $ my_fun 5 (6 :: Integer)'. – leftaroundabout

+0

Danke! Ihre Kommentare sind sehr hilfreich. –

Antwort

7

Das Problem mit Ihrem Code ist, dass Nummernliterale selbst bereits überlastet sind. So hat das Literal 6 den Typ Num a => a, während my_fun 5 den Typ F_third_arg b => b -> Integer hat. Während der Typinferenz werden also diese beiden Typvariablen vereinheitlicht. Aber da es keine anderen Anforderungen über sie sind, können GHC keine konkrete Art finden hier zu verwenden, und gibt eine entsprechende Fehlermeldung:

 
test.hs:16:26: 
    No instance for (F_third_arg a0) arising from a use of `my_fun' 
    The type variable `a0' is ambiguous 
    Possible fix: add a type signature that fixes these type variable(s) 
    Note: there are several potential instances: 
     instance F_third_arg String -- Defined at test.hs:9:10 
     instance F_third_arg Integer -- Defined at test.hs:6:10 
    In the expression: (my_fun 5) 
    In the first argument of `show', namely `((my_fun 5) $ 6)' 
    In the second argument of `($)', namely `show ((my_fun 5) $ 6)' 

test.hs:16:38: 
    No instance for (Num a0) arising from the literal `6' 
    The type variable `a0' is ambiguous 
    Possible fix: add a type signature that fixes these type variable(s) 
    Note: there are several potential instances: 
     instance Num Double -- Defined in `GHC.Float' 
     instance Num Float -- Defined in `GHC.Float' 
     instance Integral a => Num (GHC.Real.Ratio a) 
     -- Defined in `GHC.Real' 
     ...plus three others 
    In the second argument of `($)', namely `6' 
    In the first argument of `show', namely `((my_fun 5) $ 6)' 
    In the second argument of `($)', namely `show ((my_fun 5) $ 6)' 

Man könnte erwarten, dass der Compiler merkt, dass Integer die einzige Art ist, die beide erfüllt Anforderungen, aber solche Heuristiken würden Ihren Code relativ fragil machen, dh er würde brechen, nur weil Sie eine neue Instanz hinzufügen (zB F_third_arg Double). Daher lehnt der Compiler den Code ab und bittet Sie, den fraglichen Typ explizit anzugeben.

Sie haben einen Weg gefunden, es zu beheben, aber @ leftroundabouts Vorschlag, 6::Integer zu verwenden, ist ein bisschen netter.

Verwandte Themen