我想了解以下代码示例:
let rec sumlen = function
| [] -> (0,0)
| x::xs -> let (s,l) = sumlen xs in (s+x,l+1)
结果很清楚:它打印出对 sum 和 length 。但我不知道这段代码是如何工作的 例如:如果我想打印出[1; 2; 3] 的 sumlen:
sumlen [1;2;3]
let (s,l) = sumlen [2;3] in (s+1,l+1)
let (s,l) = let (s,l) = sumlen [3] in (s+2,l+1) in (s+1,l+1)
let (s,l) = let (s,l) = let(s,l) = sumlen [] in (s+3,l+1) in (s+2,l+1) in (s+1,l+1)
let (s,l) = let (s,l) = let(s,l) = (0,0) in (s+3,l+1) in (s+2,l+1) in (s+1,l+1)
我不知道我是对的,如果我说对了,为什么会这样。
我之所以需要理解这一点,是因为我必须证明
sumlen xs = ( sum xs, length xs )
有人能帮助我吗?
谢谢
答案 0 :(得分:2)
有很多方法可以理解代码。你可以像你一样重复展开文本。事实上,如果你评估它的结果是正确的:
# let (s,l) = let (s,l) = let(s,l) = (0,0) in (s+3,l+1) in (s+2,l+1) in (s+1,l+1);;
- : int * int = (6, 3)
这对于理解正在发生的事情非常有效,但它在证明事情方面效果不佳。
通常,递归与归纳的证明方法直接相关。
要证明此代码的某些内容,您可以展示两件事:
输入列表为空时有效。
如果它适用于长度为n - 1的列表,那么它适用于长度为n的列表。
这将被称为“对列表长度的归纳”。
不同的人对归纳是否真正“解释”代码如何工作有不同的反应。在我看来,它确实解释了代码。
答案 1 :(得分:0)
同意Jeffrey的回答。
我试图回答你的评论:“我在这个片段中的问题是让...在声明中。我不知道如何证明代码。”
let (s,l) = let (s,l) = let (s,l) = (3,1) in (s+2,l+1) in (s+1,l+1)
我这样重写:
let (s,l) =
let (s,l) =
let (s,l) = (3,1)
in
(s+2,l+1)
in
(s+1,l+1)
“let”绑定给定范围内的变量。内部让(s,l)绑定到(3,0)并返回(5,1);然后用于在中间范围内绑定(s,l)。然后外部let将(s,l)绑定到(6,2) - 并且这个(s,l)在顶级范围内可见。