如何在这个功能中工作?

时间:2013-09-12 20:52:22

标签: recursion functional-programming sml

此函数查找列表的最大数量,并且我很难理解它:

fun max1 (xs : int list) = 
if null xs
    then NONE
        else 
            let val tl_ans =  max1(tl xs)
        in 
            if isSome tl_ans andalso valOf tl_ans > hd xs
                then 
                    tl_ans
                else 
                    SOME (hd xs)
end;

如何在行tl_ans中计算if isSome tl_ans andalso valOf tl_ans > hd xs 既然还没有设定呢?

3 个答案:

答案 0 :(得分:2)

该功能有两种情况:

1)基础案例 - 列表为空    没有最大值,返回NONE

2)List不为空 - 由于列表不为空,列表将有一个头(第一个元素)和一个尾(除第一个之外的所有元素)。请注意,对于包含一个元素的列表,尾部将为空。

这里的想法是,对于非空列表,在函数中递归计算列表尾部的最大值,tl_ans(尾部答案或尾部最大值)。由于我们知道除了第一个元素(头部)之外的所有元素中的最大值,现在整个列表的最大值只是tl_ans和列表头部中的最大值。

在每次递归调用时,输入大小减1,因为我们只是传递列表的尾部(即没有第一个元素)。当它只有一个尾部为空的元素的列表时,这将最终调用基本情况。从那里开始,在每次递归调用的回程中,递归调用的头部将与递归返回的内容进行比较。

以下是插图:

最大[5,2,6,4]

tl_ans = max [2,6,4], hd = 5
         |
         |=>tl_ans = max [6,4], hd = 2
                   |
                   |=>tl_ans = max [4], hd = 6
                               |
                               |=>tl_ans = max [], hd = 4
                                           |
                                           |<= None (Base case)

                                <= Some 4, comparing tl_ans (None) and hd (4)
                    <== Some 6, comparing tl_ans (Some 4) and hd (6)
        <= Some 6, comparing tl_ans (Some 6) and hd (2)
<= Some 6, comparing tl_ans (some 6) and hd (5)

答案 1 :(得分:2)

这不是在标准ML中编写此类函数的最惯用的方法。我建议,以另一种方式写它将更好地理解它是如何工作的。函数valOfhdtl是所谓的partial functions,使用它们的唯一理由是确保其输入不是NONE或{分别为{1}}(在这种情况下,程序将调用异常)。

使用[]valOfhd将要求您检查列表是否为空(例如tail)或存在选项(例如{{1} }),因此使用它的便利性是有限的。相反,需要使用模式匹配(或这些函数的更多健壮版本)。

下面我以其他两种方式编写了相同的功能,其中一种类似于你提供的功能。

null xs

答案 2 :(得分:1)

let val tl_ans =  max1(tl xs)
in 
    if isSome tl_ans andalso valOf tl_ans > hd xs    

在以下代码中 tl_ansmax1 (tl xs)
(您通常会说max1 (tl xs)的值绑定到名称(或变量)“tl_ans”。)

完全相同
if isSome (max1 (tl xs)) andalso valOf (max1 (tl xs)) > hd xs

除了值max1 (tl xs)仅计算一次。