我理解并在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#的新手)
答案 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);
这里是代码的理解/英文翻译:
如果列表(您想要供电)为空,则返回一个列表,其中包含一个空列表
如果列表为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 t
,t
表示(powerset t)
中的每个元素。 < - 令人困惑的部分位于t
,t
中的(powerset 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
答案 2 :(得分:-4)
t
是由模式匹配约束的变量。 List.fold是避免显式循环的一种奇特方式。现在,去阅读一些关于F#的入门教程。