F#类型的递归树结构

时间:2016-03-14 00:16:17

标签: recursion f# tree

我仍然是F#的新手,并试图找出如何制作我自己的类型,可以容纳任何数量的" A"&之前,如果应该如何在端。

作为一个例子,它可能像:

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

如果我尝试制作这样的类型,我会尝试这样声明:

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

它告诉我,我不能两次声明相同的类型,因为我有重复。有没有办法解决这个问题,或者我真的需要让最后一个节点成为另一个名字:

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

然后结果是:

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

请帮忙吗?

2 个答案:

答案 0 :(得分: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>> }。这是优势还是劣势取决于您的更大背景。

话虽这么说,但我发现自己想知道为什么你首先想要这样做,除非作为语言句法的抽象练习。也许如果你澄清根问题和/或域名,社区就能够更好地帮助你。

答案 1 :(得分: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

现在,当您在树形结构中工作时,您需要告诉&#34;节点int&#34;除了&#34;树节点&#34; case:如果它是&#34; int&#34;的节点,你想要(比如说)提取int并在计算中使用它。但是,如果它是“树的节点”,你会想要(比如说)进一步深入到树形结构中,最终到达彩虹尽头的金罐......我的意思是,在树的末尾的int。

因此,您需要编写类似以下内容的match结构:

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

然而,如果我们做了F#试图强迫你做的事情,并且使用不同的名称来进行&#34;会包含一个int&#34;和#34;包含另一棵树&#34;案件?然后你的类型看起来像:

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#要求您为歧视联盟的不同案例使用不同标签的原因。