与F#List.Fold混淆(powerset功能)

时间:2011-05-25 15:24:28

标签: f# powerset

我理解并在F#中编写了一个典型的幂集功能(类似于Wikipedia中的算法部分)

后来我发现这个powerset的实现看起来很好而且紧凑,期望我不理解它。

let rec powerset = function
                   | [] -> [[]]
                   | h::t -> List.fold (fun xs t -> (h::t)::t::xs) [] (powerset t);

我将其分解为1步非递归函数,以找到[1; 2]的幂集并在末尾硬编码2的幂集值[[2]; []]

let right = function
                   | [] -> [[]]
                   | h::t -> List.fold (fun acc t -> (h::t)::t::acc) [] [[2]; []];

输出为[[1]; []; [1; 2]; [2]],这是正确的。

但是我期待List.Fold输出[[1; 2]; []; [1; 2]; [2]]

由于我不确定't',我修改了变量名,我确实得到了我的预期。当然,这不是[1; 2]的正确权力。

let wrong  = function
                  | [] -> [[]]
                  | h::t -> List.fold (fun acc data -> (h::t)::data::acc) [] [[2]; []];

对于我来说(那个有趣而不是h :: t的人)只是“有趣”的第二个参数的名称,但显然不是这样。那么我写的“正确”和“错误”F#函数的区别是什么?这里到底指的是什么?

谢谢! (我是F#的新手)

3 个答案:

答案 0 :(得分:2)

在“正确”示例中,t最初是模式匹配中绑定的值的名称,但它被传递给{{1}的lambda表达式中的参数t隐藏}。而在“错误”示例中,List.fold被捕获为lambda表达式中的闭包。我想也许你不打算这个捕获,而是你想要:

t

答案 1 :(得分:1)

let rec powerset = function
                   | [] -> [[]]
                   | h::t -> List.fold (fun xs t -> (h::t)::t::xs) [] (powerset t);

这里是代码的理解/英文翻译:

  1. 如果列表(您想要供电)为空,则返回一个列表,其中包含一个空列表

  2. 如果列表为h::t(头部为h,其余为t,则h为元素,t为列表)。然后:

    一个。 (powerset t):计算t

    的功率集

    B中。 (fun xs t -> (h::t)::t::xs)表示您将此功能应用/折叠到(powerset t)。更多详细信息:xs是累加器,初始化为[]xxx::xs表示您向现有的powerest xs添加内容。此处xxx(h::t)::t,这是要添加到xs头部的两个元素。 (h::t)表示add head to tt表示(powerset t)中的每个元素。 < - 令人困惑的部分位于tt中的(powerset t)是列表的其余部分,而另一个t表示(powerset t)中的元素

  3. 这是fold函数的必要翻译:

    let h::t = list
    let setfort = powerset t
    xs <- []
    foreach s in setfort do
      xs <- xs.add(t) // t is a valid subset of list
      xs <- xs.add(h::t) // t with h is also a valid subset of list
    

答案 2 :(得分:-4)

t是由模式匹配约束的变量。 List.fold是避免显式循环的一种奇特方式。现在,去阅读一些关于F#的入门教程。