2012-05-14 87 views
4

我是F#的新手,学习基础知识。我有两个模组。一个通用的一个树的数据结构称为Tree是否可以将参数传递给F#模块?

module Tree 

let rec getDescendants getChildren node = 
    seq { yield node 
      for child in getChildren node do 
      yield! getDescendants getChildren child } 

let isLeaf getChildren node = Seq.isEmpty (getChildren node) 

let getLeaves getChildren node = getDescendants getChildren node 
           |> Seq.filter (isLeaf getChildren) 

正如你可以看到,所有的功能有getChildren的说法,这是一个函数, 枚举给定类型的节点的孩子。

第二模块处理XML树的更具体的情况下:

module XmlTree 

open System.Xml.Linq 

let getXmlChildren (node : XElement) = node.Elements() 

let getDescendants = Tree.getDescendants getXmlChildren 
let getLeaves = Tree.getLeaves getXmlChildren 
let isLeaf = Tree.isLeaf getXmlChildren 

具体getXmlChildren函数为XML节点被定义,并传递给所述 咖喱Tree功能。

现在有很多代码重复。

是否有可能做到这一点? (伪)

module XmlTree = Tree with getChildren = fun (node : XElement) -> node.Elements() 

回答

9

F#不支持functors所以你不能传递参数给F#模块。在你的榜样,通过产生一个节点的孩子为对象的构造函数就足够了:

type Tree<'T>(childFn: 'T -> 'T seq) = 
    let getChildren = childFn 

    member x.getDescendants node = 
     seq { yield node 
       for child in getChildren node do 
       yield! x.getDescendants child } 

    member x.isLeaf node = node |> getChildren |> Seq.isEmpty 
    member x.getLeaves node = node |> x.getDescendants |> Seq.filter x.isLeaf 

// Type usage 
open System.Xml.Linq 
let xmlTree = new Tree<XElement>(fun x -> x.Elements()) 

对于更复杂的情况下,inheritance是要走的路。特别是,您可以将Tree<'T>声明为抽象类getChildren,并在XmlTree子类中覆盖该方法。

4

你不模块做到这一点,而是与仿制药,例如

编辑

type tree<'t>(Children:seq<tree<'t>>)= 

    member x.isLeaf() = Seq.isEmpty (Children) 

    member x.getLeaves() = 
     getDescendants Children 
     |> Seq.filter (fun x -> x.isLeaf()) 

我离开了getdescendants,但应该是足够。此外,一些类型的注释不是必需的,但都出现了所发生的事情

+0

请问您能更具体一点吗? 上述示例如何使用泛型? thx – 3dGrabber

+0

@ 3D-Grabber - 查看更新后的答案 –

+0

John,似乎你已经提供了一个通用的**类型**,可以**代表任何节点类型的树,但问题是询问一个通用的**模块**可以**在任何节点类型的树上操作**。 – TheQuickBrownFox

相关问题