首页 > 解决方案 > 具有异常构造特征的 F# 类类型

问题描述

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

type T1(?maybei1: int, ?maybei2: int) =

以下所有工作:

let t11 = T1(1, 2)
let t12 = T1(1)
let t13 = T1()

但这不是(如预期的那样):

let tuple = (1, 2)
let t14 = T1 tuple //error: expected int but given int * int

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

type T2(i1: int, i2: int) =

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

let tuple = (1, 2)
let t24 = T2 tuple //ok

但我失去了选项:

let t22 = T2(1) //error
let t23 = T2() //error

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

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) =

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

编辑

Tomas Petricek 找到了让它发挥作用的方法。够好了。

然而,正如他也提到的,还有一些东西,恕我直言,听起来并不完全正确。例如,如果没有采用元组的重载构造函数,我们最终会出现以下情况:

let tup = (1, 2)

let t1 = T (1, 2) //ok
let t2 = T tup //error

在第一次实例化中,编译器将两个参数映射为构造函数所期望的选项类型,我希望在第二次实例化中也会发生同样的情况。有谁知道它是否有原因吗?

标签: f#

解决方案


如果添加一个将显式元组作为其唯一参数的重载构造函数,则创建实例的所有方法都有效:

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

老实说,我并不完全确定将元组作为参数传递给多个参数的方法的规则是什么——这有点棘手。从逻辑上讲,您可以将成员视为一个元组,但这并不是全部,因为可选参数和编译(它被编译为普通方法),所以行为有点微妙。但是定义一个带元组的显式重载(将被编译为 take System.Tuple)就可以了!


推荐阅读