2017-10-10 38 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