2013-03-12 21 views
10

Ich versuche, den Kopf um den Funktionsanwendungsoperator ($) in Haskell zu wickeln.Versuchen, Funktion Anwendungsoperator in Haskell zu verstehen

ich durch die Beispiele gerade arbeite in Erfahren Sie eine Haskell, und ich dachte, dass ich das folgende Beispiel verstanden:

Prelude> map ($ 3) [(+4), (*10), (^2), sqrt] 
[7.0,30.0,9.0,1.7320508075688772] 

ich die folgende Variante dann versucht, das auch gut funktioniert:

Prelude> map ($ 3) [(+4), (*10), (\x -> x^2), sqrt] 
[7.0,30.0,9.0,1.7320508075688772] 

Schließlich habe ich versucht, die dritte Funktion in der Liste wie folgt modifiziert, was einen Fehler erzeugt:

Prelude> map ($ 3) [(+4), (*10), (\x -> 2^x), sqrt] 
<interactive>:53:38: 
    Ambiguous type variable `b0' in the constraints: 
     (Floating b0) 
     arising from a use of `sqrt' at <interactive>:53:38-41 
     (Integral b0) arising from a use of `^' at <interactive>:53:33 
     (Num b0) arising from the literal `3' at <interactive>:53:8 
    Probable fix: add a type signature that fixes these type variable(s) 
    In the expression: sqrt 
    In the second argument of `map', namely 
     `[(+ 4), (* 10), (\ x -> 2^x), sqrt]' 
    In the expression: map ($ 3) [(+ 4), (* 10), (\ x -> 2^x), sqrt] 
Prelude> 

Es scheint, wenn die endgültige sqrt Funktion irgendwie mit dem vorherigen Listenelement zugeordnet beginnen, wie die folgende Variante funktioniert ok:

Prelude> map ($ 3) [(+4), (*10), (\x -> 2^x)] 
[7,30,8] 

mir da jemand aufklären kann, was hier vor sich geht?

+0

eine Lektion aus diesem zu nehmen, nachdem etwas an GHCi Prompt ausprobiert, überprüfen Sie seinen * Typ *, mit ** 'Prelude>: t it' **. "Es" ist ein spezielles Wort, das sich auf das vorherige Ergebnis bezieht, und ': t' fragt nach einem Typ. Sie konnten sehen, dass die Zahlen in Ihrem letzten Beispiel keine Dezimalstellen enthalten. Nach der Eingabe von ** ': s + t' ** an der Eingabeaufforderung meldet der GHCi den Typ für jedes Ergebnis, das er erzeugt. –

Antwort

17

Die Art des verwendeten Potenzierungsoperator ist

(^) :: (Num a, Integral b) => a -> b -> a 

so, wenn Sie \x -> 2^x verwenden, erhalten Sie eine Integral Einschränkung für die 3 bekommen. Aber sqrt erzwingt eine Floating Einschränkung. So ist die Art der 3 muss

3 :: (Integral t, Floating t) => t 

erfüllen, aber es gibt keine Instanz für beide unter der Standardtyp-Liste, die Integer und Double ist, so dass die säumige ausfällt, und Sie sind mit einem zweideutigen Typ Variable links.

Wenn Sie \x -> x^2 hatte, war es nur eine Num Zwang von den ersten Funktionen und Floating von sqrt, so wurde der Typ zu Double Verzug geraten.

Sie können es, wenn Sie

(**) :: Floating a => a -> a -> a 

als Exponential-Operator verwenden, funktioniert, dann kann der Typ wieder Double vorbelegt werden.

+3

Dann konnte er es reparieren und (^) durch (**) ersetzen. – zurgl

+0

Danke Daniel und Zurgl - das klärt die Sache erheblich. Von Python kommend, umschlinge ich immer noch die Implikationen der strengen Typprüfung. –

Verwandte Themen