2017-02-17 7 views
5

Ich habe gerade angefangen, F # zu lernen, und ich versuche die ersten 10 Terme der Taylor-Serie für und zu generieren und auszuwerten. Ursprünglich schrieb ich diesen Code, es zu berechnen:Der Typ 'float -> float' passt nicht zum Typ 'float'

let fact n = function 
    | 0 -> 1 
    | _ -> [1 .. n] |> List.reduce (*) 

let taylor e = 
    let term n = (e ** n)/(fact n) 
    [1 .. 10] 
     |> List.map (term) 
     |> List.reduce (+) 

, die zu einem Fehler führt, weil die ** Betreiber nicht für int funktionieren. Offensichtlich muss ich alles auf float umwandeln, damit alles richtig funktioniert. Also:

let fact (n: float) = function 
    | 0.0 -> 1.0 
    | _ -> [1.0 .. n] |> List.reduce (*) 

let taylor (e: float) = 
    let term (n: float) = (e ** n)/(fact n) 
    [1.0 .. 10.0] 
     |> List.map (term) 
     |> List.reduce (+) 

, die die Compiler-Fehler ergibt:

EvaluatingEtotheX.fs(9,39): error FS0001: The type 'float -> float' does not match the type 
'float' 

EvaluatingEtotheX.fs(9,36): error FS0043: The type 'float -> float' does not match the type 
'float' 

(Linie 9 ist, wo let term n = (e ** n)/(fact n) ist).

Warum funktioniert das nicht? Was bedeutet dieser Fehler eigentlich genau? Warum kümmert sich der Compiler darum, dass ich eine Funktion übergebe, die float und keinen tatsächlichen float Wert liefert? Beachten Sie, dass ich gerade mit dem Lernen von F # begonnen habe, daher weiß ich nicht, warum das in diesem Fall nicht funktioniert.

+0

Up-Voting, weil ich keinen Grund sehe nicht, warum jemand es nach unten gestimmt, ohne auch nur einen Kommentar zu lassen, zu erklären, warum . –

Antwort

8

Sie mischen zwei Arten von Syntax zur Definition der fact-Funktion.

Wenn Sie das Schlüsselwort function verwenden, fügt es implizit ein Argument hinzu, das dann in den definierten Zweigen verwendet wird. Wenn Sie die Signatur Ihrer fact-Definition überprüfen, wird float -> float -> float anstelle von float -> float angezeigt. Der erste Float in Ihrer Definition entspricht n, der zweite wird hinzugefügt, indem Sie das Schlüsselwort function verwenden.

können Sie entweder die Funktion Stichwort

let fact = function 
    | 0.0 -> 1.0 
    | n -> [1.0 .. n] |> List.reduce (*) 

oder einen expliziten Spiel Ausdruck (Compiler wird die Art der n als float ableiten können, keine Notwendigkeit, sie manuell angeben)

let fact n = 
    match n with 
    | 0.0 -> 1.0 
    | _ -> [1.0 .. n] |> List.reduce (*) 

Eine Randnotiz, auch wenn es in diesem Fall kein praktisches Problem sein wird, ist das Vergleichen von Floats mit genauen Werten im Allgemeinen keine gute Idee aufgrund ihrer binären Darstellung. In Ihrem Fall ist es sinnvoll fact Betrieb auf ganze Zahlen zu halten und warf dann das Ergebnis:

let term n = (e ** n)/(float (fact (int n))) // assumes fact : int -> int 
+1

solange die Argumente für "fact" klein genug sind, um keinen Überlauf zu erzeugen ... – Onur

Verwandte Themen