Skip to content

Commit

Permalink
Add documentation sections for inline schemas
Browse files Browse the repository at this point in the history
  • Loading branch information
mlaily committed Aug 13, 2022
1 parent aea9f8c commit 90885f3
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 0 deletions.
79 changes: 79 additions & 0 deletions docs/library/JsonProvider.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,85 @@ This is not a standard feature of JSON, but it can be really convenient,
e.g. to annotate each sample when using multiple ones.
*)

(**
## Type inference hints / inline schemas
Starting with version 4.2.10 of this package, it's possible to enable basic type annotations
directly in the sample used by the provider, to complete or to override type inference.
(Only basic types are supported. See the reference documentation of the provider for the full list)
This feature is disabled by default and has to be explicitly enabled with the `InferenceMode`
static parameter.
Let's consider an example where this can be useful:
*)

type AmbiguousEntity =
JsonProvider<Sample = """
{ "code":"000", "length":"0" }
{ "code":"123", "length":"42" }
{ "code":"4E5", "length":"1.83" }
""",
SampleIsList = true>
let code = (AmbiguousEntity.GetSamples()[1]).Code
let length = (AmbiguousEntity.GetSamples()[1]).Length

(*** include-fsi-merged-output ***)

(**
In the previous example, `Code` is inferred as a `float`,
even though it looks more like it should be a `string`.
(`4E5` is interpreted as an exponential float notation instead of a string)
Now let's enable inline schemas:
*)

open FSharp.Data.Runtime.StructuralInference

type AmbiguousEntity2 =
JsonProvider<Sample = """
{ "code":"typeof<string>", "length":"typeof<float<metre>>" }
{ "code":"123", "length":"42" }
{ "code":"4E5", "length":"1.83" }
""",
SampleIsList = true,
InferenceMode = InferenceMode.ValuesAndInlineSchemasOverrides>
let code2 = (AmbiguousEntity2.GetSamples()[1]).Code
let length2 = (AmbiguousEntity2.GetSamples()[1]).Length

(*** include-fsi-merged-output ***)

(**
With the `ValuesAndInlineSchemasOverrides` inference mode, the `typeof<string>` inline schema
takes priority over the type inferred from other values.
`Code` is now a `string`, as we wanted it to be!
Note that an alternative to obtain the same result would have been to replace all the `Code` values
in the samples with unambiguous string values. (But this can be very cumbersome, especially with big samples)
If we had used the `ValuesAndInlineSchemasHints` inference mode instead, our inline schema
would have had the same precedence as the types inferred from other values, and `Code`
would have been inferred as a choice between either a number or a string,
exactly as if we had added another sample with an unambiguous string value for `Code`.
You can use either angle brackets `<>` or curly brackets `{}` when defining inline schemas.
### Units of measure
Inline schemas also enable support for units of measure.
In the previous example, the `Length` property is now inferred as a `float`
with the `metre` unit of measure (from the default SI units).
Warning: units of measures are discarded when merged with types without a unit or with a different unit.
As mentioned previously, with the `ValuesAndInlineSchemasHints` inference mode,
inline schemas types are merged with other inferred types with the same precedence.
Since values-inferred types never have units, inline-schemas-inferred types will lose their
unit if the sample contains other values...
*)

(**
## Loading WorldBank data
Expand Down
81 changes: 81 additions & 0 deletions docs/library/XmlProvider.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,86 @@ for v in Test.GetSample().Values do
The type provider generates a property `Values` that returns an array with the
values - as the `<value>` nodes do not contain any attributes or children, they
are turned into `int` values and so the `Values` property returns just `int[]`!
*)

(**
## Type inference hints / inline schemas
Starting with version 4.2.10 of this package, it's possible to enable basic type annotations
directly in the sample used by the provider, to complete or to override type inference.
(Only basic types are supported. See the reference documentation of the provider for the full list)
This feature is disabled by default and has to be explicitly enabled with the `InferenceMode`
static parameter.
Let's consider an example where this can be useful:
*)

type AmbiguousEntity =
XmlProvider<Sample = """
<Entity Code="000" Length="0"/>
<Entity Code="123" Length="42"/>
<Entity Code="4E5" Length="1.83"/>
""",
SampleIsList = true>
let code = (AmbiguousEntity.GetSamples()[1]).Code
let length = (AmbiguousEntity.GetSamples()[1]).Length

(*** include-fsi-merged-output ***)

(**
In the previous example, `Code` is inferred as a `float`,
even though it looks more like it should be a `string`.
(`4E5` is interpreted as an exponential float notation instead of a string)
Now let's enable inline schemas:
*)

open FSharp.Data.Runtime.StructuralInference

type AmbiguousEntity2 =
XmlProvider<Sample = """
<Entity Code="typeof{string}" Length="typeof{float{metre}}"/>
<Entity Code="123" Length="42"/>
<Entity Code="4E5" Length="1.83"/>
""",
SampleIsList = true,
InferenceMode = InferenceMode.ValuesAndInlineSchemasOverrides>
let code2 = (AmbiguousEntity2.GetSamples()[1]).Code
let length2 = (AmbiguousEntity2.GetSamples()[1]).Length

(*** include-fsi-merged-output ***)

(**
With the `ValuesAndInlineSchemasOverrides` inference mode, the `typeof{string}` inline schema
takes priority over the type inferred from other values.
`Code` is now a `string`, as we wanted it to be!
Note that an alternative to obtain the same result would have been to replace all the `Code` values
in the samples with unambiguous string values. (But this can be very cumbersome, especially with big samples)
If we had used the `ValuesAndInlineSchemasHints` inference mode instead, our inline schema
would have had the same precedence as the types inferred from other values, and `Code`
would have been inferred as a choice between either a number or a string,
exactly as if we had added another sample with an unambiguous string value for `Code`.
### Units of measure
Inline schemas also enable support for units of measure.
In the previous example, the `Length` property is now inferred as a `float`
with the `metre` unit of measure (from the default SI units).
Warning: units of measures are discarded when merged with types without a unit or with a different unit.
As mentioned previously, with the `ValuesAndInlineSchemasHints` inference mode,
inline schemas types are merged with other inferred types with the same precedence.
Since values-inferred types never have units, inline-schemas-inferred types will lose their
unit if the sample contains other values...
*)

(**
## Processing philosophers
In this section we look at an example that demonstrates how the type provider works
Expand Down Expand Up @@ -648,6 +727,8 @@ Focusing on element shapes let us generate a type that should be essentially the
inferred from a significant set of valid samples. This allows a smooth transition (replacing `Sample` with `Schema`)
when a schema becomes available.
Note that inline schemas (values of the form `typeof{...}`) are not supported inside XSD documents.
## Related articles
* [Using JSON provider in a library](JsonProvider.html#jsonlib) also applies to XML type provider
Expand Down

0 comments on commit 90885f3

Please sign in to comment.