我想写这样的东西:
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
编译器抱怨
NumExp
中的Exp
和getValue
之间存在冲突。甚至以下失败:
let getValue (nn : NumExp) = match nn with | Num(n) -> n
是否可以在两个使用函数的已区分联合中使用相同的大小写? DU定义本身是可以的。
我想使用相同的情况,以避免添加像
type Exp =
| NumExpExp of NumExp
| Dot of NumExp * NumExp
| Op of string * Exp * Exp
在
Exp
定义中。我觉得这里缺少一些非常基本的东西。
我有
NumExp
的原因是,我希望能够将2个Exp
插入到Dot
中(而不是2个浮点数),因为它使生成表达式更容易,但它们不能是任何Exp
,而只能是数字。编辑:我真正想知道的是,是否可以将两个DU中的两种情况视为同一实体(有点像
Exp
“includes” NumExp
)。我意识到现在Exp.Num
和NumExp.Num
是完全独立的实体。 Tomas提供了一种区分以下两种情况的好方法。 最佳答案
如果您有两个歧视的联合,且案件名称相冲突,则可以使用歧视的联合案件的全限定名称:
let getValue (NumExp.Num(n)) = n
一个更完整的示例如下所示:
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
这始终使用完全限定的名称,如果名称足够简单并且存在冲突的情况(可能导致混淆),这可能是一个好主意。
编辑:关于案例共享-没有自动执行此方法的方法,但是您的
Exp
中可以有一个仅包含NumExp
值的案例。例如这样: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
函数时,您将随后编写(注意,我们不再遇到名称冲突的问题,因此我们不需要完全限定的名称):| NumExp(Num f) -> f
| Op(op, e1, e2) -> // ...