F#歧视工会中的共同案件 [英] Shared cases in F# discriminated unions

查看:94
本文介绍了F#歧视工会中的共同案件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想写这样的东西:

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

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 Exps 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.NumNumExp.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆