Types F#返回类型上的成员约束
假设我有以下类型:Types F#返回类型上的成员约束,types,f#,constraints,Types,F#,Constraints,假设我有以下类型: type AddressLow = { FlatNo: int PinCode: string } type AddressHigh = { FlatNo: int AreaName: string PinCode: string } type PersonDataLow = { id:int name:string address: AddressLow } type Person
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类型的大小写标识符之间来回转换的次数
是否可以对返回类型使用约束,以便只编写一次函数?比如说,像这样:
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
谢谢。您是否考虑过将低位或高位嵌套在一个
地址
类型中
由于大多数数据是在两种类型的地址之间共享的,我认为将其作为一个有区别的联合或两种不同的类型不是最明智的选择。相反,只需将其属性之一设为非限制并集
最简单的方法是将AreaName
设为选项
type Address = {
FlatNo: int
AreaName : string option
PinCode: string
}
type PersonData = {
id:int
name:string
address: Address
}
然后你可以去:
let GetAddressLow () =
{FlatNo = 10; AreaName = None; PinCode = "5245"}
let GetAddressHigh () =
{FlatNo = 10; AreaName = Some "Bel Air"; PinCode = "8225"}
然后,您不需要任何花哨的东西来创建GetPerson
函数。您可以使用泛型:type PersonDataYes泛型,当然。谢谢你,李。不过,出于好奇,在F#中是否可能有带“and”和“or”条件的多成员约束?在我们的例子中,我们必须对High和Low使用不同的类型。我认为泛型可能是李所建议的最简单的解决方案。谢谢