F#类型具有不寻常的结构特征

Fra*_*ron 4 f#

我有一个像这样定义的类类型:

type T1(?maybei1: int, ?maybei2: int) =
Run Code Online (Sandbox Code Playgroud)

以下所有工作:

let t11 = T1(1, 2)
let t12 = T1(1)
let t13 = T1()
Run Code Online (Sandbox Code Playgroud)

但这个没有(如预期的那样):

let tuple = (1, 2)
let t14 = T1 tuple //error: expected int but given int * int
Run Code Online (Sandbox Code Playgroud)

另一方面,如果我将我的类型定义为:

type T2(i1: int, i2: int) =
Run Code Online (Sandbox Code Playgroud)

然后我可以通过元组构造一个实例

let tuple = (1, 2)
let t24 = T2 tuple //ok
Run Code Online (Sandbox Code Playgroud)

但我失去了选择权:

let t22 = T2(1) //error
let t23 = T2() //error
Run Code Online (Sandbox Code Playgroud)

我尝试了一个额外的构造函数:

type T3(?maybei1: int, ?maybei2: int) =
    new (i1: int, i2: int) = T3(i1, i2)

type T4(i1: int, i2: int) =
    new (?maybei1: int, ?maybei2: int) =
Run Code Online (Sandbox Code Playgroud)

但我无法得到一个可以用可选参数和元组实例化的版本.任何想法(没有委托,封装或继承,只有一种类型)?

编辑

Tomas Petricek找到了一种方法来使其发挥作用; 够好了.

然而,正如他所提到的那样,仍有一些东西,imho,听起来并不完全正确.例如,如果没有带元组的重载构造函数,我们最终会遇到以下情况:

let tup = (1, 2)

let t1 = T (1, 2) //ok
let t2 = T tup //error
Run Code Online (Sandbox Code Playgroud)

在第一个实例化中,编译器将两个参数映射到构造函数所期望的选项类型中,我希望在第二个实例化中也会出现相同的情况.有谁知道是不是有这样的原因?

Tom*_*cek 8

如果添加一个重载构造函数,它将一个显式元组作为唯一参数,那么创建实例的所有方法都可以工作:

type T(?maybei1: int, ?maybei2: int) =
    new (tup:int*int) = T(fst tup, snd tup)
    member x.Values = maybei1, maybei2

T(1)
T(1, 2)
T(maybei2=2)
let tup = (1, 2)
T tup
Run Code Online (Sandbox Code Playgroud)

老实说,我不完全确定将元组作为参数传递给多参数方法的规则是什么 - 这有点棘手.从逻辑上讲,你可以认为成员是一个元组,但由于可选参数和编译(它被编译为普通方法),这不是整个故事,因此行为有点微妙.但是定义一个带有元组的显式重载(将被编译为正在进行System.Tuple)就可以了!

  • 干得好.我尝试了各种方法,并没有找到任何有用的方法,但我错过了那个方法.很高兴知道. (2认同)