Mau*_*Mau 6 f# types discriminated-union
我想写这样的东西:
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
Run Code Online (Sandbox Code Playgroud)
编译器抱怨之间的冲突NumExp,并Exp在getValue.即便是以下失败:
let getValue (nn : NumExp) = match nn with | Num(n) -> n
Run Code Online (Sandbox Code Playgroud)
有没有办法在两个有功能的歧视联盟中使用相同的案例?DU定义本身没问题.
我想使用相同的情况来避免添加一个间接级别
type Exp =
| NumExpExp of NumExp
| Dot of NumExp * NumExp
| Op of string * Exp * Exp
Run Code Online (Sandbox Code Playgroud)
在Exp定义中.我觉得我在这里缺少一些非常基本的东西.
我之所以NumExp是我希望能够"即插即用" 2 Exps转换为Dot(而不是2个漂浮),因为它使生成的表达更容易,但他们不能有任何Exp,只是数值.
编辑:我真正想知道的是两个DU中的两个案例是否可以被视为同一个实体(有点像Exp"包括" NumExp).我现在意识到Exp.Num并且NumExp.Num是完全独立的实体.Tomas提供了一种区分下面两种情况的好方法.
Tom*_*cek 14
如果您有两个具有相互冲突的案例名称的歧视联盟,您可以使用受歧视的联合案例的完全限定名称:
let getValue (NumExp.Num(n)) = n
Run Code Online (Sandbox Code Playgroud)
更完整的示例如下所示:
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
Run Code Online (Sandbox Code Playgroud)
这总是使用完全限定的名称,如果名称足够简单并且存在冲突的情况(这可能导致混淆),这可能是一个好主意.
编辑:关于案例的共享 - 没有自动的方法,但你可以在你的案例中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
Run Code Online (Sandbox Code Playgroud)
在编写eval函数时,您将编写(请注意,我们不再存在名称冲突问题,因此我们不需要完全限定名称):
| NumExp(Num f) -> f
| Op(op, e1, e2) -> // ...
Run Code Online (Sandbox Code Playgroud)