类型(单位 - >单位)的函数是否可以在F#中静态解析类型参数?

时间:2010-01-27 22:16:37

标签: f# inline

为什么不允许这样做?

type Foo() =
    static member Bar() = ()

let inline bar<^a>() = //ERROR: unexpected infix operator in pattern
    (^a : (static member Bar : unit -> unit)())

//Hypothetical usage: let _ = bar<Foo>()

......但这样可以正常使用吗?

type Foo() =
    static member Bar() = new Foo()

let inline bar() : ^a =
    (^a : (static member Bar : unit -> ^a)())

let x : Foo = bar()

具有静态解析类型参数的函数是否需要返回已解析类型的实例?

2 个答案:

答案 0 :(得分:6)

正如您所注意到的,F#将字符序列<^视为中缀运算符,因此您需要将它们与空格分开。至于何时需要明确指定约束的问题,我认为规则是当你明确给出一个函数类型参数时,你还需要指定任何必要的约束。否则,如果F#可以推断出类型参数和约束,则无需指定它们。

因此,您的问题中的这个示例运行良好:

let inline bar() :^a =
  (^a : (static member Bar : unit -> ^a)())

就像这样:

let inline bar(x : ^a) =
  (^a : (static member Bar : unit -> unit)())

因为有一个泛型类型参数,但你没有明确地将它放在函数上,而F#可以推断出所需的约束。

另一方面,如果您尝试修改其他示例以省略显式通用参数:

let inline bar() =
  (^a : (static member Bar : unit -> unit)())

你会看到F#不允许这样做,因为它没有办法弄清楚如何为^a的任何给定调用实例化bar()。因此,您需要显式提供type参数,一旦执行,您还必须显式提供约束。

答案 1 :(得分:1)

想出来。需要尖括号内的空格以及约束。

这有效:

type Foo() =
    static member Bar() = ()

let inline bar< ^a when ^a : (static member Bar : unit -> unit) >() =
    (^a : (static member Bar : unit -> unit)())

let _ = bar<Foo>()

由此我们可以推测,如果函数返回静态解析类型的实例,则约束是可选的。有谁知道这是不是规则?