F#歧视工会中的共同案件 [英] Shared cases in F# discriminated unions
问题描述
我想写这样的东西:
type NumExp = Num of float
type Exp =
| Num of float
| Dot of NumExp * NumExp
| Op of string * Exp * Exp
let getValue (Num(n) : NumExp) = n
编译器抱怨getValue
中的NumExp
和Exp
之间存在冲突.
甚至以下失败:
The compiler complains about a conflict between NumExp
and Exp
in getValue
.
Even the following fails:
let getValue (nn : NumExp) = match nn with | Num(n) -> n
是否可以在两个使用函数的已区分联合中使用相同的大小写? DU定义本身是可以的.
Is there a way to use the same case in both discriminated unions that works with functions? The DU definitions themselves are OK.
我想使用相同的大小写,以避免添加像这样的间接级别
I want to use the same case to avoid adding a level of indirection like
type Exp =
| NumExpExp of NumExp
| Dot of NumExp * NumExp
| Op of string * Exp * Exp
Exp
定义中的
. 我觉得这里缺少一些非常基本的东西.
in the Exp
definition.
I feel I'm missing something very basic here.
我拥有NumExp
的原因是我希望能够将2个Exp
插入到Dot
中(而不是2个浮点数),因为它使生成表达式更容易,但不能任何Exp
,只是数字.
The reason I have NumExp
is that I want to be able to 'plug' 2 Exp
s into a Dot
(rather than 2 floats) because it makes generating expressions easier, but they can't be any Exp
, just numerical.
编辑:我真正想知道的是两个DU中的两种情况是否可以被视为同一实体(有点像Exp
包括" NumExp
).我现在意识到Exp.Num
和NumExp.Num
是完全独立的实体. Tomas提供了一种区分以下两种情况的好方法.
EDIT: what I really wanted to know is whether the two cases in the two DUs could be treated as the same entity (kind of like Exp
"including" NumExp
). I realise now Exp.Num
and NumExp.Num
are completely separate entities. Tomas provides a nice way of discriminating the two cases below.
推荐答案
如果您有两个带有区分的案例名称的有区别的联合,则可以使用该有区别的联合案例的全限定名称:
If you have two discriminated unions with conflicting names of cases, you can use fully qualified name of the discriminated union case:
let getValue (NumExp.Num(n)) = n
一个更完整的示例如下:
A more complete example would look like this:
let rec eval = function
| Exp.Num(f) -> f
| Exp.Dot(NumExp.Num(f1), NumExp.Num(f2)) ->
// whatever 'dot' represents
| Exp.Op(op, e1, e2) ->
// operator
这总是使用完全限定的名称,如果这些名称足够简单并且存在冲突的情况(可能导致混淆),这可能是个好主意.
This always uses fully qualified names, which is probably a good idea if the names are simple enough and there are conflicting cases (which could lead to a confusion).
编辑:关于案例共享-没有自动执行此操作的方法,但是您的Exp
中可能有一个案例,其中仅包含NumExp
的值.例如这样的
Regarding sharing of cases - there is no automatic way of doing that, but you could have a case in your Exp
that simply includes values of NumExp
. For example like this:
type NumExp =
| Num of float
type Exp =
// first occurrence of NumExp is just a name, but F# allows us to reuse
// the name of the type, so we do that (you could use other name)
| NumExp of NumExp
// other cases
编写eval
函数时,您将随后编写(请注意,我们不再遇到名称冲突的问题,因此我们不需要完全限定的名称):
When writing eval
function you would then write (note that we no longer have the issue with name clashes, so we don't need fully qualified names):
| NumExp(Num f) -> f
| Op(op, e1, e2) -> // ...
这篇关于F#歧视工会中的共同案件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!