好的,这里有个奇怪的问题。我正在使用FSharp.Data.SqlClient
从我们的数据库中获取记录。它推断的记录有几个选项类型的字段。我需要过滤掉任何选项类型都是None的记录,并在字段已知的情况下创建新记录。以下是我正在谈论的一个例子。为了解决这个问题,我创建了一个过滤器函数recordFilter
,它在所有类型的Option<'T>
包含一个值时返回我想要的类型,当它们不包含时则返回None
。F#过滤多种选项的记录
我的问题是是否有可能创建一个函数,它只是自动检查记录中的所有Option<'T>
字段是否有值。我猜这需要某种反射来遍历记录的字段。我猜这是不可能的,但我想把它扔到那里以防万一我错了。
如果这种方法是惯用的方法,那么我会很高兴听到这种说法。我只是想确保我没有错过一些更优雅的解决方案。 F#有可能让我感到惊喜。
我的动机是我正在处理几十个字段的记录,其类型为Option<'T>
。像我在这个例子中那样写出大量的match...with
声明是令人讨厌的。当只有几个领域是好的时候,当它是30+领域时,这是令人讨厌的。
type OptionRecord = {
Id: int
Attr1: int option
Attr2: int option
Attr3: int option
Attr4: int option
Attr5: int option
Attr6: int option
}
type FilteredRecord = {
Id: int
Attr1: int
Attr2: int
Attr3: int
Attr4: int
Attr5: int
Attr6: int
}
let optionRecords = [for i in 1..5 ->
{
OptionRecord.Id = i
Attr1 = Some i
Attr2 =
match i % 2 = 0 with
| true -> Some i
| false -> None
Attr3 = Some i
Attr4 = Some i
Attr5 = Some i
Attr6 = Some i
}]
let recordFilter (x:OptionRecord) =
match x.Attr1, x.Attr2, x.Attr3, x.Attr4, x.Attr5, x.Attr6 with
| Some attr1, Some attr2, Some attr3, Some attr4, Some attr5, Some attr6 ->
Some {
FilteredRecord.Id = x.Id
Attr1 = attr1
Attr2 = attr2
Attr3 = attr3
Attr4 = attr4
Attr5 = attr5
Attr6 = attr6
}
| _, _, _, _, _, _ -> None
let filteredRecords =
optionRecords
|> List.choose recordFilter
是否可以使用int选项列表而不是attr1,attr2 ... atr6? – JosephStevens
@JosephStevens这只是一个玩具的例子。实际上它是int,string,decimal等的混合体。我只是用int来表示这个具体的例子 –
Gotcha,然后是的,你将需要使用反射,因为反射并不是很好,因为它给你编译时间错误带来了一个恶意的运行时错误习惯。 – JosephStevens