2016-03-14 203 views
2

我在F#上還是很新的,並試圖弄清楚如何使自己的類型可以容納任意數量的「A」之前,如果應該如何在最後一個值。F#類型的遞歸樹結構

作爲一個例子可能是這樣的:

A(A(A(A(A(0))))). 

,如果我嘗試做這樣我試圖聲明像這樣類型:

type test = 
      | A of int 
      | A of test;; 

它告訴我,我可以」 t重複聲明兩次相同的類型。有沒有什麼辦法來解決這個還是我真的需要做的最後一個節點的另一個名字是這樣的:

type test = 
      | B of int 
      | A of test;; 

,然後結果將是:

A(A(A(A(B(0))))) 

任何幫助嗎?

+0

另一種方法是'type test = A test option' –

回答

7

我不知道這是否會滿足您的其他限制(你沒告訴我們的),但是這可以通過通用的類型很容易做到:

type test<'a> = A of 'a 

let a0 = A 0 
let a1 = A(A(0)) 
let a5 = A(A(A(A(A(0))))) 

這種方法具有這個特質具有不同數量的As的值具有不同的類型 - 即在以上片段中,a0具有類型test<int>,但是a1具有類型test<test<int>>。這是一種優勢還是劣勢取決於你的大背景。

這就是說,我發現自己想知道爲什麼你想這樣做,首先,除了作爲語言語法的抽象練習。也許如果你澄清你的根本問題和/或領域,社區將能夠更好地幫助你。

+0

非常感謝!這正是我正在尋找的。一直在閱讀f#書籍和網上很多,根本無法找到這樣的答案。我所看到的f#書在我看來寫得不是很好。再次感謝你:)! – ANACoder

+0

如果我的回答對你有幫助,你會考慮接受嗎? –

+0

哦,對不起。我第一次寫一個問題。現在應該完成謝謝:) – ANACoder

7

其他人建議的解決方法,但我建議你不要你想你的方式A(A(A(A(A(0))))),並A(A(A(A(B(0)))))(語言試圖強迫你)是一個更好的選擇。

讓我們來看看你的樹型。您有兩種不同的東西:包含其他樹節點的樹節點或包含數據的樹節點。你要做的是用相同的名稱呼叫這兩樣東西:

type test = 
      | A of int 
      | A of test 

這些名稱不是特別具有描述性。讓它們重命名爲

type Tree = 
      | Node of int 
      | Node of Tree 

現在,當你通過你的樹結構的工作,你需要從案「樹節點」除了告訴「INT的節點」的情況:如果這是一個「節點的int「,你會想要(比如說)提取int並在計算中使用它。但是如果它是一個「樹的節點」,你會想要(比如說)進一步深入樹形結構,最終到達彩虹末端的金罐......我的意思是,在結束時的int樹。

所以,你需要寫一個match結構類似如下:

let rec diveTree calculation node = 
    match node with 
     | Node a -> match a with 
        | :? int -> calculation a 
        | :? Tree -> diveTree calculation a 

但是,如果我們做了什麼F#是試圖迫使你做,並用不同名稱爲「包含一個int」和「包含另一個樹」的情況?然後你的類型將是這樣的:

type Tree = 
      | LeafNode of int 
      | TreeNode of Tree 

而且match結構會是什麼樣子:

let rec diveTree calculation node = 
    match node with 
     | LeafNode a -> calculation a 
     | TreeNode a -> diveTree calculation a 

我想你會發現後者更容易閱讀和理解前者。而是爲什麼F#要求您爲歧視聯盟的不同情況使用不同的標籤。

+0

請注意,更好的設計是使其具有通用性:'type Tree <'a> = LeafNode of'a |樹的TreeNode'。另外,名稱「樹」並不完全是這個結構的正確名稱,因爲樹通常在每個級別有多個分支(並且可以在其葉節點中保存許多不同的值),並且該結構只有一個分支(並且只是一個葉節點,所以它只能容納一個int)。但是真正的樹結構通常具有相同的基本形狀,只有TreeNode的不同定義(例如,二叉樹的TreeNode * Tree *)。所以樹在這裏是一個很好的名字。 – rmunn

+0

Ty爲你的長答案:)它清理了很多東西,當人們試圖幫助時它總是很好:)這不是我正在尋找的東西。我需要它是相同的類型。爲什麼我需要它是這樣的是一個更長的故事來解釋:)但再次,非常感謝您的答案:) – ANACoder

+1

「我需要它是同一類型。」但實際上,正如Fyodor Soikin在答覆中指出的那樣,他們將會是*不同類型的。你的葉子節點的類型是'test ',你的樹節點的類型是'test '。我認爲這會導致你的問題。你可以擴展你的問題來解釋*爲什麼*你想樹節點和葉節點是相同的類型?我有一種感覺,有更好的方式去做你想做的事情,但是我們不能給你更好的建議,直到我們知道你真的想要解決什麼問題。 – rmunn