How do I do the following?
I have several types. Each of the types have two properties in common.
type OpsFlag =
Key: FlagKey
Project: Project
Metadata: FlagMetadata option
type TimeBasedFlag =
Key: FlagKey
Project: Project
Metadata: FlagMetadata option
type Flag =
| OpsFlag of OpsFlag
| TimeBasedFlag of TimeBasedFlag
flags // Flag list
|> List.filter (fun f -> f.Project = project)
How do i now filter a list by a property “project” that all types in “Flag” have in common? I understand inheritance from a base class with these properties is not really an option.
Thank you in advance. Let me know if you need more information.
Disclaimer: I’m new to F# myself, so there may be a better way than this, but here’s my attempt.
If you have a list of DUs then I think the only way to treat them “polymorphically” is to pattern match on each flag instance.
Here’s a solution I just tried. Seems to work. (NB: I stripped out the parts from your example not relevant to the solution)
module TestFilter
type Project = {
Id: int
}
type OpsFlag = {
Project: Project
}
type TimeBasedFlag = {
Project: Project
}
type Flag =
| OpsFlag of OpsFlag
| TimeBasedFlag of TimeBasedFlag
let ops1: Flag = OpsFlag { Project = { Id = 1 }}
let ops2: Flag = OpsFlag { Project = { Id = 2 }}
let time1: Flag = TimeBasedFlag { Project = { Id = 1 }}
let time2: Flag = TimeBasedFlag { Project = { Id = 2 }}
let flags = [ops1; ops2; time1; time2]
let whereIdIs i (f: Flag) =
match f with
| OpsFlag x -> x.Project.Id
| TimeBasedFlag x -> x.Project.Id
|> (=) i
printfn "Number of elements in list: %i" (List.length flags)
flags // Flag list
|> List.filter (whereIdIs 2)
|> List.length
|> printfn "Number of elements in filtered result: %i"
Thanks for the quick reply.
Thats what i did already. (right after that post) But doing this in multiple places I kind of not what i wanted. There must be a way to keep it simpler.
In this situation I would probably add a member onto Flag called Project that returns the project for each case:
type Flag =
| OpsFlag of OpsFlag
| TimeBasedFlag of TimeBasedFlag
member this.Project =
match this with
| OpsFlag f -> f.Project
| TimeBasedFlag f -> f.Project
Then your filter code will work as you have written it, as long as the compiler already knows that the type of f is Flag. It won’t automatically infer that from calling .Project in the way that it does for a normal record field.
This works if every case has a project. If any cases don’t have a project then the member will need to return an option.