考虑以下代码......
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 ())
在评论中,似乎没有办法推断返回结果应该是联合类型,如果我们必须要求对联合类型进行限定访问,这非常冗长(这看起来很令人担忧)。 / p>
也无法创建仅接受union类型的函数并将它们作为union返回。 (在这种情况下,一个函数接受TypeOne或TypeTwo并返回UnionType)。还是有吗?是否有更好的方式与受歧视的工会合作?
答案 0 :(得分: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())
答案 1 :(得分: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