In I do not like FHIR primitive extensions I complained
They undermine the guarantuee that a 1..1 element (min 1 and max 1 means required) of a specific type will exist, making every element optional with potentially any type.
With powerful object oriented languages, you probably get some kind of Element object which normally behaves like a primitive string, bool, etc., but can also get/set extension. Maybe this just seems nice but is still tricky, or maybe it really is nice, idk.
In Gleam, primitive extensions mean wrapping every single string, bool, etc., in Primitive:
pub type Primitive(a) {
Primitive(id: Option(String), ext: List(Extension), value: Option(a))
}
I mean alternatively, you could also generate a second field, so instead of
mything: Primitive(Float)
you do something like
mything: Float,
mything_: Primitive,
thing_ for each primitive thing could be many lines of code, depending on how many primitive types you have for instance 3,788 for base R4, although the total lines of code are probably dominated by to_json/decoder fns, but adding lines to the types might feel worse idkThis is just to say, these seem like the two possible ways you slap extensions on all primitives in Gleam, and neither seems great.
Handwaving away the mechanics of profiles and slicing, and how "ungainly" the primitive extension looks in json, here are the big improvements:
What this means is you can have reasonable types from primitive extensions in Gleam. For example for US Core QuestionnaireResponse, the questionnaire field looks like this
Which in Gleam becomes
pub type UsCoreQuestionnaireresponseQuestionnaire {
UsCoreQuestionnaireresponseQuestionnaire(
id: Option(String),
extension: List(ct.Extension),
questionnaire_display: Option(String),
url: Option(String),
value: Option(String),
)
}
Overall, this UsCoreQuestionnaireresponseQuestionnaire looks like a reasonable type; it has the questionnaire_display and url fields we care about as normal fields. The underlying shape of the primitive extension sort of pokes through a bit. The original questionnaire field is now "value" which is not super clear, but eh, fine. And us_core_questionnaireresponse_to_json butchers the json and us_core_questionnaireresponse_decoder stiches it back together, but behind the scenes.
More annoying is (did you catch this just looking at the type?)
questionnaire_display and url in something, but it does feel a bit less slick compared to simply putting all the extensions in a list and saying ok now do get_questionnaire_display(extensions). But I want to try having fields for them, idk, it's a work in progress 🙃The positive side is now we can modify a specific field. The base QuestionnaireResponse resource has a canonical link which must be URL to FHIR Questionnaire resource, whereas the profile says the link can, via extension:url, be to a non-FHIR questionnaire. Plus add display via extension:questionnaireDisplay. And again now that we're using a profile, the big improvement is we don't have to slap primitive extension on literally every field, and we can use the profile to agree with other systems on element structure.
See FHIR JSON format questions by Graham Grieve (2018) and https://chat.fhir.org/#narrow/channel/179166-implementers/topic/JSON.20Format.20for.20Primitives.20.26.20extensions for some interesting backstory, but ofc it is what it is at this point
FHIR motivates customizing data structures and APIs:
there is wide variability between jurisdictions and across the healthcare ecosystem around practices, requirements, regulations, education and what actions are feasible and/or beneficial.
For this reason, the FHIR specification is a "platform specification" - it creates a common platform or foundation on which a variety of different solutions are implemented.
If the point of FHIR is to be a platform that you can twist to fit whatever use case, then primitive extensions make more sense. I still don't love them because, like, do you really need them over normal extension, plus the gross JSON, but primitive extensions do seem more usable in the context of profiles.