如何声明一个泛型函数返回满足F#中多个约束的类型?

Joh*_*Joh 3 generics f#

我想写的是:

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()
Run Code Online (Sandbox Code Playgroud)

注意mk的返回类型的类型约束.虽然它没有编译,编译器抱怨它不能将A和B转换为'T.

Tom*_*cek 7

约束是好的,但问题是,有没有类型会满足约束,这将是两者的超类型AB.

match结构需要从两个分支的返还相同种类,所以你需要向上转型添加(:>)以某种类型使得改建工程两个分支.类型可以是IXIY,但不满足约束.

这将是可能的,只有.NET允许你写的东西像IX+IY这将意味着同时实现了接口的类型.然后你也可以使用这种类型的值,例如:

let (a:IX+IY) = new A()  // This isn't supported
Run Code Online (Sandbox Code Playgroud)

我认为最好的解决方案是简单地返回一个IX * IY包含两次相同实例的元组,但表示为不同的类型.在这里你写的这个constriant非常有用:

// 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
Run Code Online (Sandbox Code Playgroud)


kvb*_*kvb 7

如果你控制的类型AB,那么最简单的解决办法是确定

type IXY =
  inherit IX
  inherit IY
Run Code Online (Sandbox Code Playgroud)

然后拥有AB继承IXY,并且mk只返回一个IXY而不是泛型类型(即使没有约束,它也无论如何都没有意义).