鉴于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
我错过了什么?
答案 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