2009-07-10 3 views
3

Ich versuche, F # zu lernen, indem sie einige der Euler Probleme gehen und ich fand eine Frage, die ich nicht in der Lage gewesen, herausfinden. Das ist meine naive Lösung.F #: Warnung FS0020: Dieser Ausdruck sollte Typ ‚Einheit‘, sondern hat Typ ‚Bool‘

let compute = 
    let mutable f = false 
    let mutable nr = 0 
    while f = false do 
     nr <- nr + 20 
     f = checkMod nr 
    nr 

Wenn ich dies tun erhalte ich die Fehlermeldung Warnung FS0020: Dieser Ausdruck sollte Typ ‚Einheit‘, sondern hat Typ ‚Bool‘ auf dem Ausdruck „nr < - nr 20“. Ich habe versucht, die Ausdrücke umzuschreiben und zu verschieben, und ich bekomme immer diesen Fehler in der Zeile unterhalb der while-Anweisung.

Ich schreibe dies mit VS2010 Beta.

Antwort

10

Die folgende Zeile:

f = checkMod nr 

ist eine Gleichheitsprüfung, keine Zuordnung, wie ich glaube, Sie beabsichtigen. Ändern Sie es in:

f <- checkMod nr 

und alles sollte gut funktionieren. Ich bin nicht sicher, warum Sie die richtige Syntax in der vorherigen Zeile und nicht diese Zeile verwendet haben ...

Auch sollte die Linie while f = false do wirklich zu while not f do vereinfacht werden; Gleichheitsprüfungen bei Booleschen Werten sind ziemlich kompliziert.

Als ich side note, ich fühle mich ein Bedürfnis darauf zu hinweisen, dass Sie effektiv versuchen, F # als imperative Sprache zu verwenden. Von der Verwendung veränderbarer Variablen und while-Schleifen wird in funktionalen Sprachen (einschließlich F #) dringend abgeraten, insbesondere wenn eine rein funktionale (und einfachere) Lösung existiert, wie in dieser Situation. Ich empfehle Ihnen, ein wenig über die Programmierung im funktionalen Stil zu lesen. Natürlich ist es einfach nützlich, sich mit der Syntax vertraut zu machen.

+0

Dank, dass das Problem gelöst Kann nicht glauben, dass ich verpasst, dass so lange :) es nach starren Mein Ziel ist es, die funktionale Programmierung Stil, aber mit wenig Zeit zu lernen, ein, es ist sehr zu studieren langsam verarbeiten. – Paxxi

+0

Ja, fair genug. Funktionale Programmierung ist oft ein enormer Schock für Programmierer, die vorher nur imperative Sprachen benutzt haben (z.B. C/C#/Java). Es erfordert eine völlig andere Denkweise, die im Laufe der Zeit erlernt werden kann. – Noldorin

+0

Aber eines der schönen Dinge an F # ist, dass Sie mit einem vertrauten Kodierungsstil (Imperativ) beginnen und in das funktionale Mindeset einsteigen können, während Sie immer noch produktiv sind. –

0

while expressions in F # nehmen ein wenig gewöhnungsbedürftig, wenn Sie von einer imperativ Sprache kommen. Jede Zeile in einem while Ausdruck muss unit (denken void von C++/C#) auswerten. Der Gesamtausdruck ergibt dann auch unit.

Im Beispiel:

nr <- nr + 20 

ausgewertet unit während

f = checkMod nr 

auf ein bool als Noldorin merkt auswertet. Dies führt dazu, dass eine Warnmeldung gemeldet wird. Sie können die Warnung sogar ausschalten, wenn Sie dies wünschen. Fügen Sie einfach Folgendes am Anfang der Datei ein:

1

Wenn Sie versuchen, den funktionalen Stil zu übernehmen, versuchen Sie, veränderliche Werte zu vermeiden.

Zum Beispiel wie folgt aus:

let nr = 
    let rec compute nr = 
     if checkMod nr then nr else compute (nr + 20) 
    compute 0  
12

Da ich diese weg Seite vorstellen kann die ‚kanonischen‘ Ort werden, um Informationen über Warnung FS0020, hier ist meine kurze Zusammenfassung der drei häufigsten Fälle, in denen Sie erhalten die Warnung und wie Sie sie beheben können.

absichtlich das Ergebnis einer Funktion verwirft, die nur für die Nebenwirkungen genannt: einen Fehler

// you are calling a function for its side-effects, intend to ignore result  
let Example1Orig() = 
    let sb = new System.Text.StringBuilder() 
    sb.Append("hi")  // warning FS0020 
    sb.Append(" there") // warning FS0020 
    sb.ToString() 

let Example1Fixed() = 
    let sb = new System.Text.StringBuilder() 
    sb.Append("hi") |> ignore 
    sb.Append(" there") |> ignore 
    sb.ToString() 

Warnung ist nützlich, den Hinweis auf (Funktion keine Wirkung hat):

// the warning is telling you useful info 
// (e.g. function does not have an effect, rather returns a value) 
let Example2Orig() = 
    let l = [1;2;3] 
    List.map (fun x -> x * 2) l // warning FS0020 
    printfn "doubled list is %A" l 

let Example2Fixed() = 
    let l = [1;2;3] 
    let result = List.map (fun x -> x * 2) l 
    printfn "doubled list is %A" result 

Verwirrender Zuweisungsoperator und Gleichheitsvergleichsoperator:

// '=' versus '<-' 
let Example3Orig() = 
    let mutable x = 3 
    x = x + 1   // warning FS0020 
    printfn "%d" x  

let Example3Fixed() = 
    let mutable x = 3 
    x <- x + 1 
    printfn "%d" x  
+0

Eine andere verwirrende Möglichkeit, diesen Fehler zu bekommen, ist den Bindestrich zu vergessen: x Jackson

0

Ich habe für eine lange Zeit in einem imperativen Stil programmiert, also musste ich mich an die Programmierung der funktionalen Programmierung gewöhnen.

In Ihrem Beispiel versuchen Sie, das erste Vielfache von 20 zu finden, das Ihren checkMod-Test besteht. Das ist der was Teil. Für den funktionalen wie Teil, empfehle ich die verfügbaren Methoden zu Sequenzen durchsuchen. Was Sie brauchen, ist das erste Element einer Sequenz ist (ein Vielfaches von 20), die den Test, wie folgt aus:

let multi20 = Seq.initInfinite (fun i -> i*20) 
let compute = multi20 |> Seq.find checkMod 

Die erste let eine unendliche Liste von twentyples erzeugt (I gemacht, dass ein nach oben). Das zweite Wort findet die erste Nummer in der Liste, die Ihren Test besteht. Ihre Aufgabe ist es, sicherzustellen, dass es tatsächlich eine Zahl gibt, die den Test besteht, aber das gilt natürlich auch für den Imperativ-Code.

Wenn Sie die beiden obigen Zeilen in einer zur Kondensation möchten, können Sie auch

let computeCryptic = Seq.initInfinite ((*) 20) |> Seq.find checkMod 

schreiben, aber ich finde, dass Stunts wie in Code ziehen kann zu Kopfschmerzen führen, wenn sie versuchen es ein paar Wochen später zu lesen .

0

In dem gleichen Geist wie Brians Beitrag, hier ist eine andere Möglichkeit, Warnung zu bekommen FS0020: Kurz gesagt, tupelte ich versehentlich die Funktion Argumente.

Als F # -Newbie hatte ich eine schwere Zeit, den Code unten zu debuggen, der für die zweite Zeile (lass bp ...) die Warnung gab FS0020: Dieser Ausdruck sollte den Typ 'unit' haben, aber type '(string ->^a -> Einheit) * string * float '. Es stellt sich heraus, dass Linie nicht das Problem überhaupt war; stattdessen war es die Druckzeile, die durcheinander war. Das Entfernen der Kommatrennzeichen aus der Argumentliste hat es behoben.

for country in wb.Regions.``Arab World``.Countries do 
    let gdp = country.Indicators.``GDP per capita (current US$)``.[2010] 
    let gdpThous = gdp/1.0e3 
    printfn "%s, %s (%.2f)" country.Name, country.CapitalCity, gdpThous