2

考虑以下代码...

type TypeOne () =
    member val Name = "" with get, set

type TypeTwo () =
    member val Name = "" with get, set
    member val Property = 0 with get, set

[<RequireQualifiedAccess>]
type UnionType =
    | TypeOne of TypeOne
    | TypeTwo of TypeTwo

// this only succeeds because we have defined the union type a
// requiring qualified access. otherwise TypeOne would be inferred
// as the union case, not the type (understandably)...

let t1 = TypeOne ()

// if we want t1 "as" the union type, we have to do the following...

let ut1 = UnionType.TypeOne t1

// the following function returns a result of type UnionType
// but we have to explicitly do this for each type

let makeUnion switch =
    match switch with
        | true -> UnionType.TypeOne (TypeOne ())
        | _ -> UnionType.TypeTwo (TypeTwo ())

正如评论中的那样,似乎无法推断返回结果应该是联合类型,如果我们必须要求对联合类型进行合格的访问,这是非常冗长的(这似乎是令人担忧的错误)。

也没有办法创建一个只接受联合类型并将它们作为联合返回的函数。(在这种情况下,一个函数接受 TypeOne 或 TypeTwo 并返回 UnionType)。或者有吗?是否有更好的方式与受歧视的工会合作?

4

2 回答 2

2
type TypeOne() =
    member val Name = "" with get, set

type TypeTwo() =
    member val Name = "" with get, set
    member val Property = 0 with get, set

type UnionType =
    | TypeOne of TypeOne
    | TypeTwo of TypeTwo

/// You can give some hints to the type checker 
/// by saying that you want a class constructor
let t1 = new TypeOne()

/// No need to use fully-qualified access on union types
let ut1 = TypeOne t1

let makeUnion switch =
    match switch with
    | true -> TypeOne (new TypeOne())
    | false -> TypeTwo (new TypeTwo())
于 2012-12-17T10:19:09.103 回答
2

正如 pad 所指出的那样——你不需要用它的父类型来限定一个联合案例——所以你可以写

let makeUnion switch =
    match switch with
    | true -> TypeOne (new TypeOne ())
    | false -> TypeTwo (new TypeTwo ())

但是,您将始终必须指定TypeOne. 如果您有多个采用相同参数的案例,这是为了避免出现歧义 - 比如

type foo=
|Bar of int
|Baz of int

然后即使知道返回类型,编译器也无法计算出返回什么。一个更常见的例子实际上是不带参数的情况——假设你决定重新定义真假:

type bool = |True |False
于 2012-12-17T10:30:39.260 回答