F# 递归总结由点列表给出的路径

F# Recursion to Summarize a Path given by List of Points

我是 F# 的新手,偶然发现了一个我感兴趣的问题。我正在尝试使用递归重新创建与 List.reduce 类似的功能。该函数使用 sumTwoPoints 计算坐标列表中两个元素和 returns 一个元素的总和。

let sumTwoPoints(x1, y1) (x2, y2) : float * float = (x1 + x2, y1 + y2)

到目前为止我做了什么:

let rec pathSum list = 
    match list with
    | [] -> failwith "Empty List"
    | head::next::rest -> sumTwoPoints head next :: rest

我的思考过程是这样的

// e0() e1() e2() e3() e4()...
// sumTwoPoints (e0 e1) = r1
// sumTwoPoints (r1 e2) = r2
// sumTwoPoints (r2 e3) = r3 
// sumTwoPoints (r3 e4) = r4
// pathSum = r4

e0表示列表中的元素。如果我们按照这个系统,head = e0tail = e1 以及 rest 列表有剩余元素。我不确定是否要将新的 r1 添加到 rest 列表中,但这是我想到的。下一步,如果我的逻辑是正确的,就是将这个新列表传递给 pathSum,但是再次获取,我不知道如何在代码中实现。

我提出的解决方案可能完全错误,如有任何建议或帮助,我们将不胜感激。

您需要修改函数以添加当前点的参数。

逻辑是它将列表的 'head' 添加到该点,然后使用该添加的结果和列表的其余部分递归调用自身。当最终用一个空列表调用它时,它只是 returns 点值。

let rec pathSum (current:float * float) list =
    match list with
    | [] -> current
    | head::rest ->
        let next = sumTwoPoints head current
        pathSum next rest

初始调用必须传递初始值 (0, 0):

pathSum (0, 0) list

跟进 Charles Mager 的回答,您需要查看列表。它可以为空 [] 或具有另一个列表的值 x::y。如果你仔细看看你的功能

sumTwoPoints : (float * float) -> (float * float) -> (float * float)
pathSum : (float * float) list -> (float * float) 

这样你就有了 rest 作为 (float * float) list 的类型,当用 pathSum 调用时,它给出了 (float * float) 的类型。这样您就可以使用函数 sumTwoPoints 而无需 next

 let rec pathSum list =
    match list with
    | [] -> (0.0, 0.0)
    | head::rest ->
        sumTwoPoints head (pathSum(rest))

最后,您需要将 failwith 更改为零,否则递归将失败。