如何防止推断类型为obj(或错误)

时间:2017-11-02 15:27:54

标签: generics f#

以下代码让我头疼

type Config() = class end
type ProgressA<'a>(v: 'a) = class end
type DoneA<'a>(v:'a) = class end

type Foo () = class end

type ProgressX = ProgressA<Foo>
type DoneX = DoneA<Foo>

let somethingElse = 1

type Foo with
    static member inline Validate (_:Config) (p:ProgressX) : Option<ProgressX> = Some p


let inline validatex c p =
    (^T : (static member Validate: ^V -> ^P -> Option<ProgressA< ^T>>) c, p)

let p1: ProgressX = Unchecked.defaultof<_>
let v1: Config = Unchecked.defaultof<_>

let c = validatex v1 p1

因为c的推断类型是Option<ProgressA<obj>>。但是,我期望的类型是Option<ProgressA<Foo>>

如果我从

更改validatex的定义
let inline validatex c p =
    (^T : (static member Validate: ^V -> ^P -> Option<ProgressA< ^T>>) c, p)

let inline validatex c p =
    (^T : (static member Validate: ^V -> ProgressA< ^T> -> Option<ProgressA< ^T>>) c, p)

我将在通话网站上收到错误

let c = validatex v1 p1

告知无法找到Validate

的方法p1

1 个答案:

答案 0 :(得分:2)

哦,天哪!我找到了解决方案......
一句话:元组!

问题似乎是类型推导者只在这种情况下正确运行,如果成员函数的参数是一个单元组参数。

type Foo with
                                  //see the double parens
    static member inline Validate ((_:Config, p:ProgressX)): Option<ProgressX> = Some p

//And then you need a lot of parens here as well
let inline validatex c p =
    (^T : (static member Validate: (^V * ProgressA< ^T>) -> Option<ProgressA< ^T>>) ((c, p)))