2017-10-10 1 views
2

Gegeben eine list von int s, ich möchte die Summe aller Elemente in der list, die einige Prädikaten p erfüllen.F # Summierung aller Ints in einer Liste

Ich bin so weit gekommen, aber es ist noch nicht ganz da. Der Compiler beschwert sich über 0 mit der Meldung: The type 'int' does not match the type 'int list -> 'a''

let sum (p, xs) = 
    let rec sum' p xs tempSum = function 
     | []  -> tempSum 
     | x::xs  -> sum' p xs tempSum + (if p x then x else 0) 
    sum' p xs 0 

Was bin ich?

+3

'List.filter p erforderlich ist |> List.sum'? –

Antwort

4

Ihre sum' Funktionsmuster sind nicht auf dem xs variable Anpassung, zu fixieren ise die match ... with Syntax, wo die ... ist die Variable, die Sie wollen auf Übereinstimmen (in Ihrem Fall xs) - der Typenkonflikt soll aufgelöst werden Das.

2
let sum p xs = 
    xs 
    |> List.sumBy (fun x -> if p x then x else 0) 
2

gibt es noch einen anderen Fehler im Code, die Sie noch nicht bemerkt haben, weil es das gleiche Ergebnis. Wie es derzeit geschrieben wird, ist Ihr Code nicht tail-rekursiv, obwohl Sie versucht haben, dies zu tun. Das liegt daran, dass die Funktionsanwendung eine engere Priorität hat als Operatoren wie +. So ist der Ausdruck sum' p xs tempSum + (if p x then x else 0) in Ihrem Code wird interpretiert als:

(sum' p xs tempSum) + (if p x then x else 0) 

wenn das, was Sie wahrscheinlich wollte, war:

sum' p xs (tempSum + (if p x then x else 0)) 

So wie du es geschrieben hat, ist das Ergebnis der verschachtelten sum' Anruf kann nicht sein, wird sofort zurückgegeben, da die Addition nach dem Zurückkehren des rekursiven Aufrufs erfolgt, sodass jeder Aufruf einen Stapelrahmen akzeptiert und Ihr Code in einer Liste mit Tausenden von Elementen fehlschlägt. Wenn Sie die Klammern um Ihren Zusatz hinzufügen, erhalten Sie die Tail-Call-Optimierung, die Sie wahrscheinlich erwartet haben.

0
let sum f = List.fold (fun s x -> if f x then s + x else s) 0 

Oder, wenn Endrekursion

let sum f xs = 
    let rec aux acc = function 
     | [] -> acc 
     | x::xs when f x -> aux (x + acc) xs 
     | _::xs -> aux acc xs 
    aux 0 xs 
Verwandte Themen