[英]F# member constraints on return type
Suppose I have following types: 假设我有以下几种类型:
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
}
Following two functions are to build the addresses: 以下两个功能用于构建地址:
let GetAddressLow () =
{AddressLow.FlatNo = 10; PinCode = "5245"}
let GetAddressHigh () =
{AddressHigh.FlatNo = 10; AreaName = "Bel Air"; PinCode = "8225"}
Following function is to build the PersonData: 以下功能是构建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
For above function, the return type is inferred as PersonDataHigh
by F#. 对于上述功能,F#将返回类型推断为
PersonDataHigh
。 Hence, to return different types for PersonData(ie PersonDataHigh
and PersonDataLow
) I have to write two different functions. 因此,要为PersonData返回不同的类型(即
PersonDataHigh
和PersonDataLow
),我必须编写两个不同的函数。
Another approach is to use discriminated unions(DU) but that involves number of conversions back and forth between DU type and case-identifiers of the DU type. 另一种方法是使用区分联合(DU),但涉及DU类型和DU类型的案例标识符之间来回转换的次数。
Is it possible to use constraints for the return type so as to write the function just once? 是否可以对返回类型使用约束以便只编写一次函数? Say, something like this:
说,像这样:
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()
}
If not, is using DU the best choice here? 如果不是,使用DU是这里的最佳选择吗? I am using F# 3.0.
我正在使用F#3.0。
Thanks. 谢谢。
Have you thought about nesting the low or highness within a single Address
type? 您是否考虑过将低位或高位嵌套在单个
Address
类型中?
Since you most of the data is shared between the two types of Address
, I don't think making it a discriminated union or two different types is the most sensible option. 由于大多数数据都是在两种类型的
Address
之间共享的,所以我认为将其设为一个有区别的联合或两种不同的类型不是最明智的选择。 Instead, just make one of its properties a disciminated union. 相反,只需使其属性之一成为有区别的联合。
The simplest way to do this is make the AreaName
an option
. 最简单的方法是将
AreaName
为option
。
type Address = {
FlatNo: int
AreaName : string option
PinCode: string
}
type PersonData = {
id:int
name:string
address: Address
}
Then you can go: 然后您可以去:
let GetAddressLow () =
{FlatNo = 10; AreaName = None; PinCode = "5245"}
let GetAddressHigh () =
{FlatNo = 10; AreaName = Some "Bel Air"; PinCode = "8225"}
You then don't need anything fancy to create your GetPerson
function. 然后,您不需要花哨的时间即可创建
GetPerson
函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.