Adding better error messages to XYShape validator

This commit is contained in:
Ozzie Gooen 2022-04-28 12:47:04 -04:00
parent d1ffac492c
commit 03cd887084
3 changed files with 62 additions and 6 deletions

View File

@ -584,6 +584,7 @@ module A = {
module A2 = { module A2 = {
let fmap = (a, b) => A.fmap(b, a) let fmap = (a, b) => A.fmap(b, a)
let joinWith = (a, b) => A.joinWith(b, a) let joinWith = (a, b) => A.joinWith(b, a)
let filter = (a,b) => A.filter(b, a)
} }
module JsArray = { module JsArray = {

View File

@ -0,0 +1,29 @@
type property = {fnName: string, propertyName: string}
type rec error =
| NotSorted(property)
| IsEmpty(property)
| NotFinite(property, float)
| DifferentLengths({fnName: string, p1Name: string, p2Name: string, p1Length: int, p2Length: int})
| Multiple(array<error>)
let mapErrorArrayToError = (errors: array<error>): option<error> => {
switch errors {
| [] => None
| [error] => Some(error)
| _ => Some(Multiple(errors))
}
}
let rec toString = (t: error) =>
switch t {
| NotSorted({fnName, propertyName}) => `${fnName} ${propertyName} is not sorted`
| IsEmpty({fnName, propertyName}) => `${fnName} ${propertyName} is empty`
| NotFinite({fnName, propertyName}, exampleValue) =>
`${fnName} ${propertyName} is not finite. Example value: ${E.Float.toString(exampleValue)}`
| DifferentLengths({fnName, p1Name, p2Name, p1Length, p2Length}) =>
`${fnName} ${p1Name} and ${p2Name} have different lengths. ${p1Name} has length ${E.I.toString(
p1Length,
)} and ${p2Name} has length ${E.I.toString(p2Length)}`
| Multiple(errors) => `Multiple Errors: ${E.A2.fmap(errors, toString) |> E.A.joinWith(", ")}`
}

View File

@ -62,13 +62,39 @@ module T = {
let toJs = (t: t) => {"xs": t.xs, "ys": t.ys} let toJs = (t: t) => {"xs": t.xs, "ys": t.ys}
} }
module Validates = { module Validator = {
type t = T.t type t = T.t
let areXsSorted = (t:t) => E.A.Floats.isSorted(T.xs(t)) let fnName = "XYShape validate"
let validate = (t:t) => { let property = (propertyName: string): Errors.property => {
let xsNotSorted = E.A.Floats.isSorted(T.xs(t)) ? None : Some("Xs are not sorted") fnName: fnName,
let xsNotFinite = E.A.Floats.getNonFinite(T.xs(t)) |> E.O.fmap(r => `Xs contain non-finite values: ${E.Float.toString(r)}`) propertyName: propertyName,
let ysNotFinite = E.A.Floats.getNonFinite(T.ys(t)) |> E.O.fmap(r => `Ys contain non-finite values: ${E.Float.toString(r)}`) }
let notSortedError = (p: string): Errors.error => NotSorted(property(p))
let notFiniteError = (p, exampleValue): Errors.error => NotFinite(property(p), exampleValue)
let isEmptyError = (propertyName): Errors.error => IsEmpty(property(propertyName))
let differentLengthsError = (t): Errors.error => DifferentLengths({
fnName: fnName,
p1Name: "Xs",
p2Name: "Ys",
p1Length: E.A.length(T.xs(t)),
p2Length: E.A.length(T.ys(t)),
})
let areXsSorted = (t: t) => E.A.Floats.isSorted(T.xs(t))
let areXsEmpty = (t: t) => E.A.length(t.xs) == 0
let getNonFiniteXs = (t: t) => t->T.xs->E.A.Floats.getNonFinite
let getNonFiniteYs = (t: t) => t->T.ys->E.A.Floats.getNonFinite
let validate = (t: t) => {
let xsNotSorted = areXsSorted(t) ? None : Some(notSortedError("Xs"))
let xsEmpty = areXsEmpty(t) ? None : Some(isEmptyError("Xs"))
let differentLengths =
E.A.length(T.xs(t)) !== E.A.length(T.ys(t)) ? Some(differentLengthsError(t)) : None
let xsNotFinite = getNonFiniteXs(t)->E.O2.fmap(notFiniteError("Xs"))
let ysNotFinite = getNonFiniteYs(t)->E.O2.fmap(notFiniteError("Ys"))
[xsNotSorted, xsEmpty, differentLengths, xsNotFinite, ysNotFinite]
->E.A.O.concatSomes
->Errors.mapErrorArrayToError
} }
} }