Types 使用F#判别联合方案作为参数类型

Types 使用F#判别联合方案作为参数类型,types,f#,Types,F#,我试图使用一个有区别的联合的特定成员作为参数类型。例如: type SomeUnion = | A of int * int | B of string type SomeType(A(i, j)) = member this.I = i member this.J = j let a = A(10, 20) let instance = SomeType(a) 但这是非法语法,并对SomeType的参数列表使用“意外符号”(“类型定义中”)进行投诉。这是有效语

我试图使用一个有区别的联合的特定成员作为参数类型。例如:

type SomeUnion =
   | A of int * int
   | B of string

type SomeType(A(i, j)) =
    member this.I = i
    member this.J = j

let a = A(10, 20)
let instance = SomeType(a)
但这是非法语法,并对SomeType的参数列表使用“意外符号”(“类型定义中”)进行投诉。这是有效语法:

let doSomethingWithA (A(i, j)) = i + j
但是类型签名是
SomeUnion->int
而不是
A->int
,并且它抱怨模式匹配不完整(考虑到签名可以理解)

那么这有可能吗?我相信F#union成员被编译成CLR类,因此理论上似乎是可能的,但实际上是吗(即不使用反射之类的东西)?否则,我想您必须采用手动OOP方式,这种方式更加冗长,并且不能保证完全匹配。

我的F#有点生疏,但也许您可以这样做(在mono上使用F#2进行测试)


我同意,令人惊讶的是,您无法匹配构造函数参数。它确实适用于普通成员

如果值错误,您可以在构造函数中进行显式匹配,以获得运行时错误:

type SomeType(a) =
    let i, j = match a with | A(k, l) -> k, l
    member this.I = i
    member this.J = j
但除此之外,我们必须理解
A
不是一种类型。因此
dosomethingwhitha
的类型并非如您所预期的那样并不奇怪。您将不得不忍受不完整的模式匹配警告。

正如wmeyer指出的,“A”DU的大小写根本不是一个类型,而只是union类型的一个组件

如果您真的想自己重用其中一个联合案例,我看不到任何替代方案可以使其成为显式独立类型

选项一是仅使用类型别名:

type TypeA = int * int

type SomeUnion =
    | A of TypeA 
    | B of string

type SomeType(a:TypeA) =
    let (i,j) = a
    member this.I = i
    member this.J = j

let a = (10, 20)
let instance = SomeType(a)
为了清晰起见,我在构造函数中添加了
TypeA
注释

第二种选择是将其包装在单个案例中

type TypeA = TA of int * int

type SomeUnion =
    | A of TypeA 
    | B of string

type SomeType(a:TypeA) =
    let (TA(i,j)) = a  
    member this.I = i
    member this.J = j

let a = TA (10, 20)
let instance = SomeType(a)

(请注意,match
let(TA(i,j))=a
必须有额外的参数,以避免与函数混淆。)

您不需要有区别的并集:)或者找到其他东西,或者重新思考。@RamonSnir好的,大多数时候,我确实希望有一个受歧视的联盟,因为我有一套密封的选择,我希望能够经常匹配。然而,偶尔我想特别保证一个备选方案,并使用其参数。我不想因为这些罕见的案例而放弃歧视性工会的好处,事实就是这样。你不能保证这一点,因为既没有编译器也没有运行时检查你是否收到某个DU case作为参数。这看起来更好,但意味着我必须为每个类型创建一个函数来匹配模式并提取参数。在没有更自然的语言语法的情况下,这可能是我能做的最好的了。这仍然只能推断
a
SomeType
,因此你提到的不完全匹配。当你说
A
不是一个类型时,事实上它是一个类型,因为编译器会发出IL,其中每个替代项都是一个嵌套类(参见示例)。我希望有人能肯定地确认,没有自然的处理方式;当然,它已经开始这么看了。@fhubs:它是以IL类型实现的。但是在F#语言级别上,DU案例不能作为类型访问。
type TypeA = TA of int * int

type SomeUnion =
    | A of TypeA 
    | B of string

type SomeType(a:TypeA) =
    let (TA(i,j)) = a  
    member this.I = i
    member this.J = j

let a = TA (10, 20)
let instance = SomeType(a)