reimplement parsePlot with yup

This commit is contained in:
Vyacheslav Matyukhin 2022-08-19 15:17:31 +04:00
parent 61051ffe5f
commit 7866203ac4
No known key found for this signature in database
GPG Key ID: 3D2A774C5489F96C

View File

@ -1,5 +1,5 @@
import * as yup from "yup";
import { Distribution, result, squiggleExpression } from "@quri/squiggle-lang"; import { Distribution, result, squiggleExpression } from "@quri/squiggle-lang";
import { flattenResult, resultBind } from "./utility";
export type LabeledDistribution = { name: string; distribution: Distribution }; export type LabeledDistribution = { name: string; distribution: Distribution };
@ -15,76 +15,47 @@ function ok<a, b>(x: a): result<a, b> {
return { tag: "Ok", value: x }; return { tag: "Ok", value: x };
} }
function parseString(expr: squiggleExpression): result<string, string> { const schema = yup
if (expr.tag === "string") { .object()
return ok(expr.value); .strict()
} else { .noUnknown()
return error("Expression was not string"); .shape({
} distributions: yup.object().shape({
} tag: yup.mixed().oneOf(["array"]),
value: yup
function parseRecord( .array()
expr: squiggleExpression .of(
): result<{ [key: string]: squiggleExpression }, string> { yup.object().shape({
if (expr.tag === "record") { tag: yup.mixed().oneOf(["record"]),
return ok(expr.value); value: yup.object().shape({
} else { name: yup.object().shape({
return error("Expression was not a record"); tag: yup.mixed().oneOf(["string"]),
} value: yup.string().required(),
} }),
distribution: yup.object().shape({
function parseDistribution( tag: yup.mixed().oneOf(["distribution"]),
expr: squiggleExpression value: yup.mixed(),
): result<Distribution, string> { }),
if (expr.tag === "distribution") { }),
return ok(expr.value); })
} else {
return error("Expression was not a distribution");
}
}
function parseArray(
expr: squiggleExpression
): result<squiggleExpression[], string> {
if (expr.tag === "array") {
return ok(expr.value);
} else {
return error("Expression was not a distribution");
}
}
function parseField<a>(
record: { [key: string]: squiggleExpression },
field: string,
parser: (expr: squiggleExpression) => result<a, string>
): result<a, string> {
if (record[field]) {
return parser(record[field]);
} else {
return error("record does not have field " + field);
}
}
function parseLabeledDistribution(
x: squiggleExpression
): result<LabeledDistribution, string> {
return resultBind(parseRecord(x), (record) =>
resultBind(parseField(record, "name", parseString), (name) =>
resultBind(
parseField(record, "distribution", parseDistribution),
(distribution) => ok({ name, distribution })
) )
) .required(),
); }),
} });
export function parsePlot(record: { export function parsePlot(record: {
[key: string]: squiggleExpression; [key: string]: squiggleExpression;
}): result<Plot, string> { }): result<Plot, string> {
return resultBind(parseField(record, "distributions", parseArray), (array) => try {
resultBind( const plotRecord = schema.validateSync(record);
flattenResult(array.map(parseLabeledDistribution)), return ok({
(distributions) => ok({ distributions }) distributions: plotRecord.distributions.value.map((x) => ({
) name: x.value.name.value,
); distribution: x.value.distribution.value,
})),
});
} catch (e) {
const message = e instanceof Error ? e.message : "Unknown error";
return error(message);
}
} }