2017-10-10 41 views
2

給定listint s,我想返回list中滿足某些謂詞p的所有元素的總和。F#總結列表中的所有整數

我已經到了這裏,但它還沒有到那裏。編譯器上0抱怨與消息: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 

我缺少什麼?

+3

'List.filter P |> List.sum'? –

回答

4

sum'功能沒有圖案的xs可變匹配,解決它的ISE語法match ... with...是要匹配的變量(在你的情況xs) - 類型不匹配,應通過解決那。

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

在你的代碼中還有一個你沒有注意到的錯誤,因爲它產生了相同的結果。正如它目前所寫的,即使你已經嘗試過,你的代碼並不是尾遞歸的。這是因爲功能應用比+等運營商的優先級更高。因此,在你的代碼的表達sum' p xs tempSum + (if p x then x else 0)被解釋爲:

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

時,你可能想要的是:

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

你寫它的方式,嵌套sum'調用的結果不能因爲在遞歸調用返回之後發生添加,所以立即返回,所以每次調用都會使用堆棧框架,並且您的代碼在數千個項目列表中失敗。通過在你的添加周圍添加括號,你會得到你可能期望的尾部呼叫優化。

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

或者,如果尾遞歸需要

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