Okay, strange question here. I'm using FSharp.Data.SqlClient to get records from our Database. The records that it infers have several fields which are option types. I need to filter out the records where the ANY of the option types are None and create new records where the fields are known. The following is an example of what I am talking about. To solve this I created a filter function, recordFilter, which returns the type I want in the case that all of the types of Option<'T> contain a value and a None when they do not.
My question is whether it is possible to create a function which just automatically checks all of the Option<'T> fields in the record for having a value. I'm guessing this would require reflection of some kind to iterate through the fields of the record. I'm guessing this isn't possible but I wanted to throw this out there in case I'm wrong.
If this approach is the idiomatic way, then I would be happy to hear that. I just wanted to make sure that I was not missing out on some more elegant solution. What is possible with F# consistently surprises me.
My motivation is that I am dealing with records with dozens of fields which have a type of Option<'T>. It is annoying to have to write out a massive match...with statement as I do in this example. When it is only a few fields is fine, when it is 30+ fields, it is annoying.
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