F#汇总列表中的所有整数

时间:2017-10-10 15:53:29

标签: list recursion f#

鉴于list int,我想要返回list中满足某个谓词p的所有元素的总和。

我已经到了这么远,但还没到那里。编译器在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

我错过了什么?

4 个答案:

答案 0 :(得分:4)

您的sum'函数在xs变量上没有模式匹配,要修复match ... with语法,其中...是您希望的变量匹配(在您的情况下为xs) - 类型不匹配应由此解决。

答案 1 :(得分:2)

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

答案 2 :(得分: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'调用的结果不能立即返回,因为在递归调用返回后发生了添加,所以每次调用都需要一个堆栈帧,你的代码会失败数千项的清单。通过在添加中添加括号,您将获得您可能期望的尾调用优化。

答案 3 :(得分: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