我想写这样的东西:

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中的ExpgetValue之间存在冲突。
甚至以下失败:
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.NumNumExp.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) -> // ...

08-05 04:39