来自类型提供程序 (XmlProvider) 的约束类型

Constrained types from a type provider (XmlProvider)

我从 XmlProvider 中获得了巨大的价值,因为它在我加载 XML 或 XSD 时为我提供了大量类型定义。但是,考虑一下 XML:

<period>
    <start>01/01/2018</start>
    <end>02/02/2018</end>
</period>

我可以甜言蜜语让类型提供者给我一个受约束的数据类型,这样 "end" 可能不会先于 "start"。或者也许在 XmlProvider 完成繁重的工作后加上一些约束?

在这种情况下,我会将其视为边缘情况,并将其视为 "unvalidated model"。因此,通常在 F# 中,我们会使用验证函数将未验证的模型转换为已验证的模型。 (我通常为此使用 Result<'T, 'E>。)

let validateXmlDates xml =
    if xml.period.start > xml.period.end then
        Error "Period start must be before period end"
    else Ok xml

现在,您所做的任何事情都应该有一个 Result<XmlType, string>,这样您就可以在保证它符合您的要求的情况下传递它。您还可以使用 Result.bind 链接验证 1:

Ok xml
|> Result.bind (validateXmlDates)
|> Result.bind (validateXml...)
|> Result.bind (validateXml...)

一些相关阅读:Railway Oriented Programming (F# for Fun and Profit)

获得结果后,可以使用一个简单的 match 来触发下一步:

match validatedXml with
| Ok xml -> ...
| Error str -> ...

然后您将在 Ok 分支中执行下一个逻辑步骤,并在 Error 分支中处理错误。

1:Result.bind (fn) 实际上是以下内容的缩写:

match result with
| Error e -> Error e
| Ok v -> fn v