为什么不允许这样做?
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()
具有静态解析类型参数的函数是否需要返回已解析类型的实例?
答案 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>()
由此我们可以推测,如果函数返回静态解析类型的实例,则约束是可选的。有谁知道这是不是规则?