我想写的是什么:
type A() =
interface IX with ...
interface IY with ...
type B() =
interface IX with ...
interface IY with ...
let mk t : 'T when 'T :> IX and 'T :> IY =
match t with
| Choice1 -> new A()
| Choice2 -> new B()
注意mk返回类型的类型约束。但它没有编译,编译器抱怨它无法将A和B转换为'T。
答案 0 :(得分:7)
约束是可以的,但问题是没有类型可以满足约束,并且它将是A
和B
的超类型。
match
构造需要从两个分支返回相同的类型,因此您需要将upcast(:>
)添加到某种类型,以便转换适用于两个分支。类型可以是IX
或IY
,但这不符合约束条件。
只有当.NET允许您编写类似IX+IY
的内容时,这才有可能,这意味着实现两个接口的类型。然后你也可以使用这种类型的值,例如:
let (a:IX+IY) = new A() // This isn't supported
我认为最好的解决方案是简单地返回一个包含两次相同实例的元组IX * IY
,但表示为不同的类型。在这里,你写的这个悔改非常有用:
// Type: 'a -> IX * IY when 'a :> IX and 'a :> IY
let asTuple a = (a :> IX, a :> IY)
let mk t =
match t with
| Choice1Of2() -> new A() |> asTuple
| Choice2Of2() -> new B() |> asTuple
答案 1 :(得分:7)
如果您控制类型A
和B
,那么最简单的解决方案就是定义
type IXY =
inherit IX
inherit IY
然后让A
和B
继承IXY
,而mk
只返回IXY
而不是通用类型(实际上并非如此)无论如何,即使没有约束,也要有意义。)