【问题标题】:Confused with F# List.Fold (powerset function)与 F# List.Fold 混淆(powerset 函数)
【发布时间】:2011-05-25 15:24:27
【问题描述】:

我理解并用 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]; []];

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

谢谢! (我是 F# 新手)

【问题讨论】:

    标签: f# powerset


    【解决方案1】:

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

    //now it works as you expect, replaced "t" with "data" in your lambda expression.
    let wrong  = function
                      | [] -> [[]]
                      | h::t -> List.fold (fun acc data -> (h::data)::data::acc) [] [[2]; []];
    

    【讨论】:

    • 谢谢!这正是我所需要的,现在整个功能都有意义了。 't' 参数让我寻找不存在的模式 :) !
    【解决方案2】:
    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是一个列表)。那么:

      A. (powerset t):计算t的幂集

      B. (fun xs t -> (h::t)::t::xs) 表示您将此函数应用/折叠到(powerset t)。更多细节:xs 是一个累加器,它被初始化为[]xxx::xs 表示您在现有的最强大的 xs 中添加一些内容。这里xxx(h::t)::t,这是要添加到xs头部的两个元素。 (h::t) 表示add head to tt 表示(powerset t) 中的每个元素。 t,(powerset t) 中的t 是列表的其余部分,而另一个t 表示(powerset t) 中的一个元素。

    这是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
    

    【讨论】:

    • 感谢您对函数的解释,尤其是令人困惑的部分。这真的让我很困惑! :)
    【解决方案3】:

    t 是模式匹配绑定的变量。 List.fold 是一种避免显式循环的奇特方式。现在,去阅读一些关于 F# 的介绍性教程。

    【讨论】:

    • 我确实读过 List.Fold 和 t(尾部),但我不明白折叠中的 't' 表示什么。有那么明显吗?对不起,我只是看不到它:-/
    猜你喜欢
    • 1970-01-01
    • 2019-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-20
    • 1970-01-01
    • 2016-04-08
    相关资源
    最近更新 更多