问题描述
||
我了解并在F#中编写了一个典型的幂集函数(类似于Wikipedia中的Algorithms部分)
后来我发现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#的新手)
解决方法
在您的“正确”示例中,
t
最初是模式匹配中绑定的值的名称,但是在传递给List.fold
的lambda表达式中,参数by5ѭ将其隐藏。而在您的“错误”示例中,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]; []];
,let rec powerset = function
| [] -> [[]]
| h::t -> List.fold (fun xs t -> (h::t)::t::xs) [] (powerset t);
这是对代码的理解/英语翻译:
如果列表(您要打开电源)为空,则返回一个列表,其中包含一个空列表
如果列表是h::t
(头为h
,其余为t
,则h
是元素,and5ѭ是列表)。然后:
A.(powerset t)
:计算t
的幂集
B.(fun xs t -> (h::t)::t::xs)
表示您将此功能应用于/折叠到(powerset t)
。更多详细信息:xs
是累加器,它被初始化为[]
。 xxx::xs
表示您在现有功能最强大的ѭ20add上添加了一些内容。 xxx
是(h::t)::t
,这是要添加到ѭ20head开头的两个元素。 (h::t)
表示add head to t
,t
表示(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
,“ 5”是受模式匹配限制的变量。 List.fold是避免显式循环的一种理想方法。现在,去阅读一些有关F#的入门教程。