2016-03-14 143 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