使用F#实现树构建器(Implement tree builder with F#)
我是F#的新手,我想实现以下问题的解决方案:从随机顺序发现的一系列磁盘路径(例如“C:\ Hello \ foo”“C:”,“C:\ Hello \ bar “等......)如何构建(有效)树。 假设:序列有效,这意味着可以有效地创建树。
所以我尝试使用递归函数(下面的“mergeInto”)实现,该函数将树“就地”与字符串列表(称为“branch”的分割路径)合并在一起
这是我的实现,不变性防止了对输入树的副作用,所以我尝试使用ref单元格作为输入树,但我遇到了递归的困难。 有解决方案吗
open Microsoft.VisualStudio.TestTools.UnitTesting type Tree = |Node of string*list<Tree> |Empty let rec branchToTree (inputList:list<string>) = match inputList with | [] -> Tree.Empty | head::tail -> Tree.Node (head, [branchToTree tail]) //branch cannot be empty list let rec mergeInto (tree:Tree ref) (branch:list<string>) = match !tree,branch with | Node (value,_), head::tail when String.op_Inequality(value, head) -> raise (ApplicationException("Oops invariant loop broken")) | Node (value,_), [_] -> ignore() //the branch is singleton and by loop invariant its head is the current Tree node -> nothing to do. | Node (value,children), _ -> let nextBranchValue = branch.Tail.Head //valid because of previous match //broken attempt to retrieve a ref to the proper child let targetChild = children |> List.map (fun(child) -> ref child) |> List.tryFind (fun(child) -> match !child with |Empty -> false |Node (value,_) -> value = nextBranchValue) match targetChild with |Some x -> mergeInto x branch.Tail //a valid child match then go deeper. NB: branch.Tail cannot be empty here |None -> tree := Node(value, (Node (nextBranchValue,[])) :: children)//attach the next branch value to the children | Empty,_ -> tree := branchToTree branch [<TestClass>] type TreeTests () = [<TestMethod>] member this.BuildTree () = let initialTree = ref Tree.Empty let branch1 = ["a";"b";"c"] let branch2 = ["a";"b";"d"] do mergeInto initialTree branch1 //-> my tree is ok do mergeInto initialTree branch2 //->not ok, expected a // | // b // / \ // d c
I am pretty new to F# and I wanted to implement a solution to the following problem: From a sequence of disk paths discovered in random order (e.g. "C:\Hello\foo" "C:" , "C:\Hello\bar" etc....) how to build (efficiently) the tree. Assumption: the sequence is valid, which means the tree can be effectively created.
So I tried to implement with a recursive function ("mergeInto" in the following) which merges the tree "in place" with a list of string (the splitted path called "branch")
Here is my implementation, the immutability prevents side effects on the input tree, so I tried to use a ref cell for the input Tree but I encounter difficulty with the recursion. Any solution ?
open Microsoft.VisualStudio.TestTools.UnitTesting type Tree = |Node of string*list<Tree> |Empty let rec branchToTree (inputList:list<string>) = match inputList with | [] -> Tree.Empty | head::tail -> Tree.Node (head, [branchToTree tail]) //branch cannot be empty list let rec mergeInto (tree:Tree ref) (branch:list<string>) = match !tree,branch with | Node (value,_), head::tail when String.op_Inequality(value, head) -> raise (ApplicationException("Oops invariant loop broken")) | Node (value,_), [_] -> ignore() //the branch is singleton and by loop invariant its head is the current Tree node -> nothing to do. | Node (value,children), _ -> let nextBranchValue = branch.Tail.Head //valid because of previous match //broken attempt to retrieve a ref to the proper child let targetChild = children |> List.map (fun(child) -> ref child) |> List.tryFind (fun(child) -> match !child with |Empty -> false |Node (value,_) -> value = nextBranchValue) match targetChild with |Some x -> mergeInto x branch.Tail //a valid child match then go deeper. NB: branch.Tail cannot be empty here |None -> tree := Node(value, (Node (nextBranchValue,[])) :: children)//attach the next branch value to the children | Empty,_ -> tree := branchToTree branch [<TestClass>] type TreeTests () = [<TestMethod>] member this.BuildTree () = let initialTree = ref Tree.Empty let branch1 = ["a";"b";"c"] let branch2 = ["a";"b";"d"] do mergeInto initialTree branch1 //-> my tree is ok do mergeInto initialTree branch2 //->not ok, expected a // | // b // / \ // d c
原文:https://stackoverflow.com/questions/17364840
最满意答案
我认为beta减少可以指定单步和多步beta减少。
我可以说beta减少可以从
(/x./y./zx) ab
产生/za
,但我不能说单步β减少可以做到这一点。你所说的其余部分是正确的。
I would think that beta reduction can designate both single and multi step beta reductions.
I can say that beta reduction can yield
/z.a
from(/x./y./z.x) a b
, but I cannot say that a single step beta reduction can do that.The rest of what you said is correct.
相关问答
更多-
我认为beta减少可以指定单步和多步beta减少。 我可以说beta减少可以从(/x./y./zx) ab产生/za ,但我不能说单步β减少可以做到这一点。 你所说的其余部分是正确的。 I would think that beta reduction can designate both single and multi step beta reductions. I can say that beta reduction can yield /z.a from (/x./y./z.x) a b, but ...
-
lambda演算的β减少:评估顺序重要吗?(Beta reduction in lambda calculus: Order of evaluation important?)[2023-10-03]
我问我的TA,他说应用程序是关联的,意思是 (\kf.f(\c.co)km)(\x.dox)(\le.le) 相当于 ( [\kf.( [ f(\c.co) ]k )m ][\x.dox] )[ \le.le ] 这解释了为什么k不能应用于(\c.co) 。:/ 括号/括号仅用于使其更具可读性。 问候。 I asked my TA, he said that application is left associative, meaning (\kf.f(\c.co)km)(\x.dox)(\le.le) ... -
那么容易,那么我想: class Test: @staticmethod def mul(x,y): return x*y FUNC1 = staticmethod(lambda y: Test.mul(y,2)) FUNC2 = staticmethod(lambda y: lambda x: Test.mul(y,x)) print Test.FUNC1(2) print Test.FUNC2(2)(3) 这工作 well that was easier ...
-
大概你想避免多次通过,因为管道阶段可能很昂贵。 或者您希望避免收集中间值以便通过多个收集器运行它们,因为存储所有值的成本可能太高。 正如Brian Goetz所指出的 , Collectors.summarizingInt将收集int值并对它们执行多次约简,返回一个名为IntSummaryStatistics的聚合结构。 有类似的收集器用于汇总double和long值。 不幸的是,它们只执行一组固定的减少,所以如果你想减少与它们不同的减少,你必须编写自己的收集器。 这是一种在一次通过中使用多个不相关的收集器 ...
-
你可能想尝试像这样的cbv战术 : Definition foo := (fun (x : nat) => x) 42. Definition bar := (fun (x : nat) => x) 42. Goal foo = bar. cbv delta [foo]. 这导致以下证明状态: (fun x : nat => x) 42 = bar You might want to try e.g. the cbv tactic like so: Definition foo := (fun ( ...
-
减少Lambda微积分(Reduction in Lambda Calculus)[2023-03-24]
Beta降低只是lambda演算中用于计算的主要应用规则。 它通过替换应用,如下所示: 如果你有lambda术语:(\ xx)和右边的一些值:y 然后,您将所有绑定变量替换为lambda术语中(。)的右侧。 绑定变量是与(。)左边的变量匹配的变量,因此在这种情况下为x。 The reduction would be of the form: (\x.x)y //y gets bound to all occurences of x to the right of the period y 其中y绑定 ... -
音频降噪(audio noise reduction)[2023-07-15]
SoX是一个跨平台的命令行应用程序,可以进行音频操作。 快速检查手册页显示它可以降噪(参见noiseprof和noisered )。 您可以将trim与noiseprof结合使用,选择较大音频文件的小片段作为噪音。 SoX is a cross-platform command-line application that does audio manipulation. A quick check of the man page reveals that it can do noise reduction ... -
BetaBinomial与“Beta和Binomial”之间的区别(Difference between BetaBinomial and “Beta and Binomial”)[2023-02-18]
每个样本需要一个单独的p ( shape参数是新的): with pm.Model() as model1: alpha1 = pm.Uniform('alpha', 1, 100) beta1 = pm.Uniform('beta', 1, 100) p1 = pm.Beta('prob', alpha=alpha1, beta=beta1, shape=1000) X1 = pm.Binomial('X1', n=n_data, p=p1, observed=x_data ... -
恢复步骤: Y = ƛf.( ƛx.f(xx)) ( ƛx.f(xx)) = ƛf.( f ( ƛx.f(xx) ƛx.f(xx) ) ) = ƛf.( f ( f (ƛx.f(xx) ƛx.f(xx)))) = ƛf.( f ( f ( f (ƛx.f(xx) ƛx.f(xx)))) = ƛf.( f ( f ( f ( f (ƛx.f(xx) ƛx.f(xx))))) = ... 所以这个Lambda术语进入无限循环...... 说明: 让我们看一下术语( ƛx.f(xx) ƛx.f ...
-
减少是一种你可以用块做的操作。 最简单的解决方案是在GPU上分配两个数据缓冲区和两个结果缓冲区,然后通过执行缩减内核重叠传输到GPU。 当GPU忙时,您的CPU可以减少连续GPU减少的输出。 这样,您可以分摊大部分数据传输成本,并处理部分缩减结果。 您可以使用带有CUDA示例的标准缩减内核NVIDIA供应来完成所有这些工作。 Reduction is an operation which you can do in chunks. The simplest solution would be to allo ...