简体   繁体   中英

F# | Generics with 'or' Constraints on Lists

I have the following two types:

 type MedicalConditionStore = { MedicalCondition: MedicalCondition LastMod: UTCTick } type RejectedMedicalConditionStore = { RejectedMedicalCondition: MedicalCondition LastMod: UTCTick }

And I would like to create the following method:

 let accumulateConditions medicalConditionsList =...

Where medicalConditionsList could be either MedicalConditionStore list or a RejectedMedicalConditionStore list

Intuitively, I was thinking to combine Generics with Constraints, but I cannot manage to find the proper syntax to do that. I have tried something like this, but it doesn't work:

 let accumulateConditions (medicalConditionsList: ^a list when ^a:(member F: MedicalCondition)) =...

Or like this:

 let accumulateConditions (medicalConditionsList: RejectedMedicalConditionStore list | MedicalConditionStore list) =...

Anyone has a clue on how to approach this, without creating another discriminated union type over both of them - a situation in which I always need to wrap and unwrap the members from their general type to the specific one and vice versa using pattern matching?

Thank you

You would be able to achieve this using static member constraints, but I think that is a wrong approach - it will result in fragile and complex code.

As mentioned in the comments, I think it would make much more sense to reconsider your domain. The best design really depends on all the different things that can be done with medical conditions. You could mark conditions with their state:

 type MedicalConditionState = Rejected | Accepted type MedicalConditionStore = { MedicalCondition: MedicalCondition LastMod: UTCTick State: MedicalConditionState }

Or you could keep two separate lists at a higher level:

 type MedicalConditionStore = { MedicalCondition: MedicalCondition LastMod: UTCTick } type MedicalConditions = { Accepted: MedicalConditionStore list Rejected: MedicalConditionStore list }

Alternatively, as you seem to want to access just the underlying MedicalCondition , you could also use good-old-fashioned-interface type, which is a perfectly reasonable thing to do in F# (although in this case, I think revisiting your domain model would solve the problem more elegantly):

 type IMedicalCondition = abstract MedicalCondition: MedicalCondition type MedicalConditionStore = { MedicalCondition: MedicalCondition LastMod: UTCTick } interface IMedicalCondition with member x.MedicalCondition = x.MedicalCondition type RejectedMedicalConditionStore = { RejectedMedicalCondition: MedicalCondition LastMod: UTCTick } interface IMedicalCondition with member x.MedicalCondition = x.RejectedMedicalCondition let accumulateConditions (medicalConditionsList:seq<#IMedicalCondition>) = // (...)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM