我仍然是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)))))
请帮忙吗?
答案 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#要求您为歧视联盟的不同案例使用不同标签的原因。