【发布时间】:2017-12-18 07:36:12
【问题描述】:
假设我有以下类型:
type AddressLow = {
FlatNo: int
PinCode: string
}
type AddressHigh = {
FlatNo: int
AreaName: string
PinCode: string
}
type PersonDataLow = {
id:int
name:string
address: AddressLow
}
type PersonDataHigh = { //same label names, different type for address
id:int
name:string
address: AddressHigh
}
以下两个函数是构建地址:
let GetAddressLow () =
{AddressLow.FlatNo = 10; PinCode = "5245"}
let GetAddressHigh () =
{AddressHigh.FlatNo = 10; AreaName = "Bel Air"; PinCode = "8225"}
以下功能是构建 PersonData:
let GetPerson fGetAddress inputId inputName = //return type inferred as PersonDataHigh
{
id = inputId
name = inputName
address = fGetAddress()
}
let p1 = GetPerson GetAddressLow 4 "John Smith" //compile error
let p2 = GetPerson GetAddressHigh 6 "Will Smith" //works
对于上述函数,返回类型被 F# 推断为PersonDataHigh。
因此,要返回不同类型的 PersonData(即 PersonDataHigh 和 PersonDataLow),我必须编写两个不同的函数。
另一种方法是使用可区分联合 (DU),但这涉及 DU 类型和 DU 类型的 case-identifiers 之间的来回转换次数。
是否可以对返回类型使用约束以便只编写一次函数?说,像这样:
let inline GetPerson (fGetAddress) (inputId) (inputName)
: ^T when ^T: (member id: int) and ^T: (member name: string) and (^T: (member address: AddressLow) or ^T: (member address: AddressHigh)) = //compile error
{
id = inputId
name = inputName
address = fGetAddress()
}
如果不是,那么在这里使用 DU 是不是最好的选择?我正在使用 F# 3.0。
谢谢。
【问题讨论】:
-
你可以使用泛型:
type PersonData<'T> = { id : int; name : string; address: 'T } -
当然是泛型。谢谢李。只是出于好奇,是否可以在 F# 中使用“and”和“or”条件有多个成员约束?
标签: types f# constraints