I derive great value from XmlProvider as it gives me a ton of type definitions when I load an XML or XSD. However, consider this XML:
<period>
<start>01/01/2018</start>
<end>02/02/2018</end>
</period>
Can I sweet talk the type provider into giving me a constrained data type such that "end" may not precede "start". Or maybe bolt on some constraints after XmlProvider does the heavy lifting?
In this case I would treat this as an edge-case, and consider it an "unvalidated model". As such, typically in F#, we would use a validation function to turn that unvalidated model into a validated model. (I usually use Result<'T, 'E> for that.)
let validateXmlDates xml =
if xml.period.start > xml.period.end then
Error "Period start must be before period end"
else Ok xml
Now, anything you do should expect a Result<XmlType, string>, which will allow you to pass it around with a guarantee that it matches your requirements. You may also use Result.bind to chain validations1:
Ok xml
|> Result.bind (validateXmlDates)
|> Result.bind (validateXml...)
|> Result.bind (validateXml...)
Somewhat related reading: Railway Oriented Programming (F# for Fun and Profit)
Once you have the results, a trivial match can be used to trigger the next step:
match validatedXml with
| Ok xml -> ...
| Error str -> ...
You would then do the next logical step in the Ok branch, and handle errors in the Error branch.
1: Result.bind (fn) is effectively a short-hand for the following:
match result with
| Error e -> Error e
| Ok v -> fn v
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With