2012-05-14 107 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

相關問題