f#具有多个tupled参数的静态成员约束

Eri*_*ric 3 f#

从f#我试图使用成员约束在C#定义的对象上调用函数.由于c#成员函数接受多个参数,因此f#编译器将其视为元组,但在应用泛型成员约束时,我得到一个错误,该函数接受4个参数,但我只提供了一个.

我已经尝试从参数中形成元组或只是采用预先设置的参数集,但两者都给出了相同的错误.我想我必须错误地定义我的成员约束,但是没有很多带有多个参数的成员约束的例子.

let inline wrapForDecode (buffer:DirectBuffer) (offset:int) (blockLen:uint16) (version:uint16) : ^a =
  let msg = new ^a()
  (^a : (member WrapForDecode : (DirectBuffer*int*int*int)->unit) msg, (buffer, offset, (int blockLen), (int version)))
  msg

let inline wrapForDecode2 (args :DirectBuffer*int*int*int) : ^a =
  let msg = new ^a()
  (^a : (member WrapForDecode : (DirectBuffer*int*int*int)->unit) (msg, args))
  msg
Run Code Online (Sandbox Code Playgroud)

原始的WrapForDecode成员函数在c#中定义如下:

public void WrapForDecode(DirectBuffer buffer, int offset, int actingBlockLength, int actingVersion) {...}
Run Code Online (Sandbox Code Playgroud)

当我尝试调用该函数时,我得到了wrapForDecode或wrapForDecode2的以下错误.

The member or object constructor 'WrapForDecode' takes 4 argument(s) but is here given 1. The required signature is 'MDInstrumentDefinitionFuture27.WrapForDecode(buffer: DirectBuffer, offset: int, actingBlockLength: int, actingVersion: int) : unit'.
Run Code Online (Sandbox Code Playgroud)

pia*_*ste 7

如果将WrapForDecode参数的类型更改(DirectBuffer*int*int*int)DirectBuffer*int*int*int第一个内联方法将编译:

let inline wrapForDecode (buffer:string) 
                         (offset:int)
                         (blockLen:uint16)
                         (version:uint16)
                         : ^a =
  let msg = new ^a()
  (^a : (member WrapForDecode : string * int * int * int -> unit) 
      msg, 
      buffer, 
      offset, 
      (int blockLen), 
      (int version))
  msg

type foo () = 
    member this.WrapForDecode (a : string, b: int, c: int, d:int) = 
        ()

let x : foo = wrapForDecode "asd" 1 2us 3us
Run Code Online (Sandbox Code Playgroud)

在普通的F#代码中,两个签名是等价的 - 所有方法都只需要一个参数,并且要编写一个arity> 1的函数,它必须是curry或者是一个tupled参数.

但是,这不是CLI的工作原理 - 在C#/ VB.Net中,foo1(x : bar, y : baz)有一个不同的签名foo2(xy : Tuple<bar, baz>).

通常,F#编译器会自动在两种样式之间进行转换,因此从F#访问非F#.NET代码时,您会看到这两种方法都采用了一个tupled参数.

但静态解析的成员约束是F#的复杂且相对边缘的特征,因此在以这种方式调用方法时,似乎不能或不能执行此自动转换.

(感谢@ildjarn指出这种差异的来源)

  • `member WrapForDecode:(string * int * int * int)-&gt; unit`是一元方法(单个参数是4元组)。`member WrapForDecode:string * int * int * int-&gt; unit`是一种四元方法。这些是完全不同的类型。;-] (2认同)