我想定义一个受歧视联盟的所有成员共享的方法。目前我已经像这样实现了它,但它似乎真的不太优雅 - 当然还有更好的方法。建议?
type A =
{AData:string}
member this.SharedMethod (x:float) : int= ...
type B =
{BData:float}
member this.SharedMethod (x:float) : int= ...
type AB =
| A of A
| B of B
let CallSharedMethod (ab:AB) x =
match ab with
| AB.A(a') -> a'.SharedMethod x
| AB.B(b') -> b'.SharedMethod x
答案 0 :(得分:18)
这样的事情怎么样?
type AB =
| A of string
| B of float
member self.SharedMethod (x : float) =
match self with
| A s -> x
| B f -> f + x
这假设您希望sum类型的每个变体(也称为区别联合)使用float参数执行不同的操作。
对于A
的情况,我只返回原始值,因为我无法做其他事情(因为string
和float
之间没有普遍有用的关系产生了float
)。
答案 1 :(得分:8)
在您的示例中,您使用实例成员扩充 记录类型A
和B
。但是,您不仅可以扩充记录类型,还可以扩充 union 类型(如@Rodrick的答案中所示)。如果你这样做,联盟的扩充将由每个DU案例“共享”,这就是你所要求的。为了使其更加明确,我已经重命名了您示例的某些部分:
type A = { AData:string }
type B = { BData:float }
type AB =
| ACase of A
| BCase of B
member __.SharedMethod x = 0
let callSharedMethod (ab:AB) x = ab.SharedMethod x
如果查看对象浏览器(或ILSpy之类的反编译器)中的编译代码,您将看到AB
被编译为两个子类AB.ACase
和{{1}的基类},AB.BCase
属于基类SharedMethod
。
另见F# 3.0 specification:联盟类型成员的第8.5.1节。