A playground based on reducer
This commit is contained in:
parent
61b589d0bd
commit
cb07f5f68a
|
@ -1,124 +0,0 @@
|
|||
import * as React from "react";
|
||||
import _ from "lodash";
|
||||
import type { Spec } from "vega";
|
||||
import type {
|
||||
DistPlus,
|
||||
} from "@quri/squiggle-lang";
|
||||
import { createClassFromSpec } from "react-vega";
|
||||
import * as chartSpecification from "../vega-specs/spec-distributions.json";
|
||||
|
||||
let SquiggleVegaChart = createClassFromSpec({
|
||||
spec: chartSpecification as Spec,
|
||||
});
|
||||
|
||||
export const DistPlusChart: React.FC<{
|
||||
distPlus: DistPlus;
|
||||
width: number;
|
||||
height: number;
|
||||
}> = ({ distPlus, width, height }) => {
|
||||
let shape = distPlus.pointSetDist;
|
||||
if (shape.tag === "Continuous") {
|
||||
let xyShape = shape.value.xyShape;
|
||||
let totalY = xyShape.ys.reduce((a, b) => a + b);
|
||||
let total = 0;
|
||||
let cdf = xyShape.ys.map((y) => {
|
||||
total += y;
|
||||
return total / totalY;
|
||||
});
|
||||
let values = _.zip(cdf, xyShape.xs, xyShape.ys).map(([c, x, y]) => ({
|
||||
cdf: (c * 100).toFixed(2) + "%",
|
||||
x: x,
|
||||
y: y,
|
||||
}));
|
||||
|
||||
return (
|
||||
<SquiggleVegaChart
|
||||
width={width}
|
||||
height={height}
|
||||
data={{ con: values }}
|
||||
actions={false}
|
||||
/>
|
||||
);
|
||||
} else if (shape.tag === "Discrete") {
|
||||
let xyShape = shape.value.xyShape;
|
||||
let totalY = xyShape.ys.reduce((a, b) => a + b);
|
||||
let total = 0;
|
||||
let cdf = xyShape.ys.map((y) => {
|
||||
total += y;
|
||||
return total / totalY;
|
||||
});
|
||||
let values = _.zip(cdf, xyShape.xs, xyShape.ys).map(([c, x, y]) => ({
|
||||
cdf: (c * 100).toFixed(2) + "%",
|
||||
x: x,
|
||||
y: y,
|
||||
}));
|
||||
|
||||
return <SquiggleVegaChart data={{ dis: values }} actions={false} />;
|
||||
} else if (shape.tag === "Mixed") {
|
||||
let discreteShape = shape.value.discrete.xyShape;
|
||||
let totalDiscrete = discreteShape.ys.reduce((a, b) => a + b);
|
||||
|
||||
let discretePoints = _.zip(discreteShape.xs, discreteShape.ys);
|
||||
let continuousShape = shape.value.continuous.xyShape;
|
||||
let continuousPoints = _.zip(continuousShape.xs, continuousShape.ys);
|
||||
|
||||
interface labeledPoint {
|
||||
x: number;
|
||||
y: number;
|
||||
type: "discrete" | "continuous";
|
||||
}
|
||||
|
||||
let markedDisPoints: labeledPoint[] = discretePoints.map(([x, y]) => ({
|
||||
x: x,
|
||||
y: y,
|
||||
type: "discrete",
|
||||
}));
|
||||
let markedConPoints: labeledPoint[] = continuousPoints.map(([x, y]) => ({
|
||||
x: x,
|
||||
y: y,
|
||||
type: "continuous",
|
||||
}));
|
||||
|
||||
let sortedPoints = _.sortBy(markedDisPoints.concat(markedConPoints), "x");
|
||||
|
||||
let totalContinuous = 1 - totalDiscrete;
|
||||
let totalY = continuousShape.ys.reduce((a: number, b: number) => a + b);
|
||||
|
||||
let total = 0;
|
||||
let cdf = sortedPoints.map((point: labeledPoint) => {
|
||||
if (point.type === "discrete") {
|
||||
total += point.y;
|
||||
return total;
|
||||
} else if (point.type === "continuous") {
|
||||
total += (point.y / totalY) * totalContinuous;
|
||||
return total;
|
||||
}
|
||||
});
|
||||
|
||||
interface cdfLabeledPoint {
|
||||
cdf: string;
|
||||
x: number;
|
||||
y: number;
|
||||
type: "discrete" | "continuous";
|
||||
}
|
||||
let cdfLabeledPoint: cdfLabeledPoint[] = _.zipWith(
|
||||
cdf,
|
||||
sortedPoints,
|
||||
(c: number, point: labeledPoint) => ({
|
||||
...point,
|
||||
cdf: (c * 100).toFixed(2) + "%",
|
||||
})
|
||||
);
|
||||
let continuousValues = cdfLabeledPoint.filter(
|
||||
(x) => x.type === "continuous"
|
||||
);
|
||||
let discreteValues = cdfLabeledPoint.filter((x) => x.type === "discrete");
|
||||
|
||||
return (
|
||||
<SquiggleVegaChart
|
||||
data={{ con: continuousValues, dis: discreteValues }}
|
||||
actions={false}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
38
packages/components/src/components/DistributionChart.tsx
Normal file
38
packages/components/src/components/DistributionChart.tsx
Normal file
|
@ -0,0 +1,38 @@
|
|||
import * as React from "react";
|
||||
import _ from "lodash";
|
||||
import type { Spec } from "vega";
|
||||
import type {
|
||||
Distribution,
|
||||
} from "@quri/squiggle-lang";
|
||||
import { distributionErrorToString } from '@quri/squiggle-lang';
|
||||
import { createClassFromSpec } from "react-vega";
|
||||
import * as chartSpecification from "../vega-specs/spec-distributions.json";
|
||||
|
||||
let SquiggleVegaChart = createClassFromSpec({
|
||||
spec: chartSpecification as Spec,
|
||||
});
|
||||
|
||||
type DistributionChartProps = {
|
||||
distribution: Distribution;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export const DistributionChart: React.FC<DistributionChartProps> = ({ distribution, width, height }: DistributionChartProps) => {
|
||||
console.log("Making shape")
|
||||
let shape = distribution.shape();
|
||||
console.log(shape)
|
||||
if (shape.tag === "Ok") {
|
||||
return (
|
||||
<SquiggleVegaChart
|
||||
data={{ con: shape.value.continuous, dis: shape.value.discrete }}
|
||||
width={width}
|
||||
height={height}
|
||||
actions={false}
|
||||
/>
|
||||
);
|
||||
}
|
||||
else{
|
||||
return <> {distributionErrorToString(shape.value)} </>;
|
||||
}
|
||||
};
|
|
@ -1,10 +1,10 @@
|
|||
import * as React from "react";
|
||||
import _ from "lodash";
|
||||
import type { Spec } from "vega";
|
||||
import type { DistPlus } from "@quri/squiggle-lang";
|
||||
import type { Distribution, errorValue, result } from "@quri/squiggle-lang";
|
||||
import { createClassFromSpec } from "react-vega";
|
||||
import * as percentilesSpec from "../vega-specs/spec-percentiles.json";
|
||||
import { DistPlusChart } from "./DistPlusChart";
|
||||
import { DistributionChart } from "./DistributionChart";
|
||||
import { Error } from "./Error";
|
||||
|
||||
let SquigglePercentilesChart = createClassFromSpec({
|
||||
|
@ -13,36 +13,38 @@ let SquigglePercentilesChart = createClassFromSpec({
|
|||
|
||||
type distPlusFn = (
|
||||
a: number
|
||||
) => { tag: "Ok"; value: DistPlus } | { tag: "Error"; value: string };
|
||||
) => result<Distribution, errorValue>
|
||||
|
||||
const _rangeByCount = (start, stop, count) => {
|
||||
const _rangeByCount = (start: number, stop: number, count: number) => {
|
||||
const step = (stop - start) / (count - 1);
|
||||
const items = _.range(start, stop, step);
|
||||
const result = items.concat([stop]);
|
||||
return result;
|
||||
};
|
||||
|
||||
function unwrap<a, b>( x: result<a, b>): a {
|
||||
if(x.tag === "Ok"){
|
||||
return x.value
|
||||
}
|
||||
}
|
||||
export const FunctionChart: React.FC<{
|
||||
distPlusFn: distPlusFn;
|
||||
diagramStart: number;
|
||||
diagramStop: number;
|
||||
diagramCount: number;
|
||||
}> = ({ distPlusFn, diagramStart, diagramStop, diagramCount }) => {
|
||||
let [mouseOverlay, setMouseOverlay] = React.useState(NaN);
|
||||
let [mouseOverlay, setMouseOverlay] = React.useState(0);
|
||||
function handleHover(...args) {
|
||||
setMouseOverlay(args[1]);
|
||||
}
|
||||
function handleOut(...args) {
|
||||
function handleOut() {
|
||||
setMouseOverlay(NaN);
|
||||
}
|
||||
const signalListeners = { mousemove: handleHover, mouseout: handleOut };
|
||||
let percentileArray = [
|
||||
0.01, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.95, 0.99,
|
||||
];
|
||||
let mouseItem = distPlusFn(mouseOverlay);
|
||||
let showChart =
|
||||
mouseItem.tag === "Ok" ? (
|
||||
<DistPlusChart distPlus={mouseItem.value} width={400} height={140} />
|
||||
<DistributionChart distribution={mouseItem.value} width={400} height={140} />
|
||||
) : (
|
||||
<></>
|
||||
);
|
||||
|
@ -56,22 +58,21 @@ export const FunctionChart: React.FC<{
|
|||
})
|
||||
.filter((x) => x !== null)
|
||||
.map(({ x, value }) => {
|
||||
let percentiles = getPercentiles(percentileArray, value);
|
||||
return {
|
||||
x: x,
|
||||
p1: percentiles[0],
|
||||
p5: percentiles[1],
|
||||
p10: percentiles[2],
|
||||
p20: percentiles[3],
|
||||
p30: percentiles[4],
|
||||
p40: percentiles[5],
|
||||
p50: percentiles[6],
|
||||
p60: percentiles[7],
|
||||
p70: percentiles[8],
|
||||
p80: percentiles[9],
|
||||
p90: percentiles[10],
|
||||
p95: percentiles[11],
|
||||
p99: percentiles[12],
|
||||
p1: unwrap(value.inv(0.01)),
|
||||
p5: unwrap(value.inv(0.05)),
|
||||
p10: unwrap(value.inv(0.12)),
|
||||
p20: unwrap(value.inv(0.20)),
|
||||
p30: unwrap(value.inv(0.30)),
|
||||
p40: unwrap(value.inv(0.40)),
|
||||
p50: unwrap(value.inv(0.50)),
|
||||
p60: unwrap(value.inv(0.60)),
|
||||
p70: unwrap(value.inv(0.70)),
|
||||
p80: unwrap(value.inv(0.80)),
|
||||
p90: unwrap(value.inv(0.90)),
|
||||
p95: unwrap(value.inv(0.95)),
|
||||
p99: unwrap(value.inv(0.99)),
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -101,88 +102,3 @@ export const FunctionChart: React.FC<{
|
|||
);
|
||||
};
|
||||
|
||||
function getPercentiles(percentiles: number[], t: DistPlus) {
|
||||
if (t.pointSetDist.tag === "Discrete") {
|
||||
let total = 0;
|
||||
let maxX = _.max(t.pointSetDist.value.xyShape.xs);
|
||||
let bounds = percentiles.map((_) => maxX);
|
||||
_.zipWith(
|
||||
t.pointSetDist.value.xyShape.xs,
|
||||
t.pointSetDist.value.xyShape.ys,
|
||||
(x, y) => {
|
||||
total += y;
|
||||
percentiles.forEach((v, i) => {
|
||||
if (total > v && bounds[i] === maxX) {
|
||||
bounds[i] = x;
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
return bounds;
|
||||
} else if (t.pointSetDist.tag === "Continuous") {
|
||||
let total = 0;
|
||||
let maxX = _.max(t.pointSetDist.value.xyShape.xs);
|
||||
let totalY = _.sum(t.pointSetDist.value.xyShape.ys);
|
||||
let bounds = percentiles.map((_) => maxX);
|
||||
_.zipWith(
|
||||
t.pointSetDist.value.xyShape.xs,
|
||||
t.pointSetDist.value.xyShape.ys,
|
||||
(x, y) => {
|
||||
total += y / totalY;
|
||||
percentiles.forEach((v, i) => {
|
||||
if (total > v && bounds[i] === maxX) {
|
||||
bounds[i] = x;
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
return bounds;
|
||||
} else if (t.pointSetDist.tag === "Mixed") {
|
||||
let discreteShape = t.pointSetDist.value.discrete.xyShape;
|
||||
let totalDiscrete = discreteShape.ys.reduce((a, b) => a + b);
|
||||
|
||||
let discretePoints = _.zip(discreteShape.xs, discreteShape.ys);
|
||||
let continuousShape = t.pointSetDist.value.continuous.xyShape;
|
||||
let continuousPoints = _.zip(continuousShape.xs, continuousShape.ys);
|
||||
|
||||
interface labeledPoint {
|
||||
x: number;
|
||||
y: number;
|
||||
type: "discrete" | "continuous";
|
||||
}
|
||||
|
||||
let markedDisPoints: labeledPoint[] = discretePoints.map(([x, y]) => ({
|
||||
x: x,
|
||||
y: y,
|
||||
type: "discrete",
|
||||
}));
|
||||
let markedConPoints: labeledPoint[] = continuousPoints.map(([x, y]) => ({
|
||||
x: x,
|
||||
y: y,
|
||||
type: "continuous",
|
||||
}));
|
||||
|
||||
let sortedPoints = _.sortBy(markedDisPoints.concat(markedConPoints), "x");
|
||||
|
||||
let totalContinuous = 1 - totalDiscrete;
|
||||
let totalY = continuousShape.ys.reduce((a: number, b: number) => a + b);
|
||||
|
||||
let total = 0;
|
||||
let maxX = _.max(sortedPoints.map((x) => x.x));
|
||||
let bounds = percentiles.map((_) => maxX);
|
||||
sortedPoints.map((point: labeledPoint) => {
|
||||
if (point.type === "discrete") {
|
||||
total += point.y;
|
||||
} else if (point.type === "continuous") {
|
||||
total += (point.y / totalY) * totalContinuous;
|
||||
}
|
||||
percentiles.forEach((v, i) => {
|
||||
if (total > v && bounds[i] === maxX) {
|
||||
bounds[i] = total;
|
||||
}
|
||||
});
|
||||
return total;
|
||||
});
|
||||
return bounds;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
import * as React from "react";
|
||||
import _ from "lodash";
|
||||
import { run } from "@quri/squiggle-lang";
|
||||
import { run, errorValueToString } from "@quri/squiggle-lang";
|
||||
import type {
|
||||
SamplingInputs,
|
||||
samplingParams,
|
||||
exportEnv,
|
||||
exportDistribution,
|
||||
} from "@quri/squiggle-lang";
|
||||
import { NumberShower } from "./NumberShower";
|
||||
import { DistPlusChart } from "./DistPlusChart";
|
||||
import { FunctionChart } from "./FunctionChart";
|
||||
import { DistributionChart } from "./DistributionChart";
|
||||
import { Error } from "./Error";
|
||||
|
||||
export interface SquiggleChartProps {
|
||||
|
@ -39,8 +37,6 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = ({
|
|||
squiggleString = "",
|
||||
sampleCount = 1000,
|
||||
outputXYPoints = 1000,
|
||||
kernelWidth,
|
||||
pointDistLength = 1000,
|
||||
diagramStart = 0,
|
||||
diagramStop = 10,
|
||||
diagramCount = 20,
|
||||
|
@ -49,43 +45,35 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = ({
|
|||
width = 500,
|
||||
height = 60,
|
||||
}: SquiggleChartProps) => {
|
||||
let samplingInputs: SamplingInputs = {
|
||||
let samplingInputs: samplingParams = {
|
||||
sampleCount: sampleCount,
|
||||
outputXYPoints: outputXYPoints,
|
||||
kernelWidth: kernelWidth,
|
||||
pointDistLength: pointDistLength,
|
||||
xyPointLength: outputXYPoints
|
||||
};
|
||||
|
||||
let result = run(squiggleString, samplingInputs, environment);
|
||||
console.log(result)
|
||||
if (result.tag === "Ok") {
|
||||
let environment = result.value.environment;
|
||||
let exports = result.value.exports;
|
||||
onEnvChange(environment);
|
||||
let chartResults = exports.map((chartResult: exportDistribution) => {
|
||||
if (chartResult["NAME"] === "Float") {
|
||||
return <NumberShower precision={3} number={chartResult["VAL"]} />;
|
||||
} else if (chartResult["NAME"] === "DistPlus") {
|
||||
return (
|
||||
<DistPlusChart
|
||||
distPlus={chartResult.VAL}
|
||||
height={height}
|
||||
width={width}
|
||||
/>
|
||||
);
|
||||
} else if (chartResult.NAME === "Function") {
|
||||
return (
|
||||
<FunctionChart
|
||||
distPlusFn={chartResult.VAL}
|
||||
diagramStart={diagramStart}
|
||||
diagramStop={diagramStop}
|
||||
diagramCount={diagramCount}
|
||||
/>
|
||||
);
|
||||
}
|
||||
});
|
||||
return <>{chartResults}</>;
|
||||
let chartResult = result.value;
|
||||
if (chartResult.tag === "number") {
|
||||
return <NumberShower precision={3} number={chartResult.value} />;
|
||||
} else if (chartResult.tag === "distribution") {
|
||||
console.log("Is a distribution")
|
||||
return (
|
||||
<DistributionChart
|
||||
distribution={chartResult.value}
|
||||
height={height}
|
||||
width={width}
|
||||
/>
|
||||
);
|
||||
console.log("NOT THIS LINE")
|
||||
}
|
||||
else {
|
||||
console.log("Is a distribution")
|
||||
return <Error heading="No Viewer">{"We don't currently have a viewer for this type: " + chartResult.tag}</Error>;
|
||||
}
|
||||
} else if (result.tag === "Error") {
|
||||
// At this point, we came across an error. What was our error?
|
||||
return <Error heading={"Parse Error"}>{result.value}</Error>;
|
||||
return <Error heading={"Parse Error"}>{errorValueToString(result.value)}</Error>;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -4,8 +4,8 @@ import type {
|
|||
exportDistribution,
|
||||
} from "../rescript/ProgramEvaluator.gen";
|
||||
export type { exportEnv, exportDistribution };
|
||||
import { genericDist, samplingParams, evaluate, expressionValue, errorValue, distributionError } from "../rescript/TypescriptInterface.gen";
|
||||
export { makeSampleSetDist } from "../rescript/TypescriptInterface.gen";
|
||||
import { genericDist, samplingParams, evaluate, expressionValue, errorValue, distributionError, toPointSet, continuousShape, discreteShape, distributionErrorToString } from "../rescript/TypescriptInterface.gen";
|
||||
export { makeSampleSetDist, errorValueToString, distributionErrorToString } from "../rescript/TypescriptInterface.gen";
|
||||
import {
|
||||
Constructors_mean,
|
||||
Constructors_sample,
|
||||
|
@ -32,19 +32,14 @@ import {
|
|||
Constructors_pointwiseLogarithm,
|
||||
Constructors_pointwisePower,
|
||||
} from "../rescript/Distributions/DistributionOperation/DistributionOperation.gen";
|
||||
export type {samplingParams, errorValue}
|
||||
|
||||
export type SamplingInputs = {
|
||||
readonly sampleCount?: number;
|
||||
readonly outputXYPoints?: number;
|
||||
readonly kernelWidth?: number;
|
||||
readonly pointDistLength?: number
|
||||
};
|
||||
export let defaultSamplingInputs: samplingParams = {
|
||||
sampleCount: 10000,
|
||||
xyPointLength: 10000
|
||||
};
|
||||
|
||||
type result<a, b> =
|
||||
export type result<a, b> =
|
||||
| {
|
||||
tag: "Ok";
|
||||
value: a;
|
||||
|
@ -65,6 +60,10 @@ export function resultMap<a, b, c>(
|
|||
}
|
||||
}
|
||||
|
||||
function Ok<a,b>(x: a): result<a,b> {
|
||||
return {"tag": "Ok", value: x}
|
||||
}
|
||||
|
||||
type tagged<a, b> = {tag: a, value: b}
|
||||
|
||||
function tag<a,b>(x: a, y: b) : tagged<a, b>{
|
||||
|
@ -97,9 +96,6 @@ function createTsExport(x: expressionValue, sampEnv: samplingParams): squiggleEx
|
|||
return tag("number", x.value);
|
||||
case "EvRecord":
|
||||
return tag("record", _.mapValues(x.value, x => createTsExport(x, sampEnv)))
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,6 +104,19 @@ export function resultExn<a, c>(r: result<a, c>): a | c {
|
|||
return r.value;
|
||||
}
|
||||
|
||||
export type point = { x: number, y: number}
|
||||
|
||||
export type shape = {
|
||||
continuous: point[]
|
||||
discrete: point[]
|
||||
}
|
||||
|
||||
function shapePoints(x : continuousShape | discreteShape): point[]{
|
||||
let xs = x.xyShape.xs;
|
||||
let ys = x.xyShape.ys;
|
||||
return _.zipWith(xs, ys, (x, y) => ({x, y}))
|
||||
}
|
||||
|
||||
export class Distribution {
|
||||
t: genericDist;
|
||||
env: samplingParams;
|
||||
|
@ -148,6 +157,34 @@ export class Distribution {
|
|||
);
|
||||
}
|
||||
|
||||
shape() : result<shape, distributionError> {
|
||||
let pointSet = toPointSet(this.t, {xyPointLength: this.env.xyPointLength, sampleCount: this.env.sampleCount}, null);
|
||||
if(pointSet.tag === "Ok"){
|
||||
let distribution = pointSet.value;
|
||||
if(distribution.tag === "Continuous"){
|
||||
return Ok({
|
||||
continuous: shapePoints(distribution.value),
|
||||
discrete: []
|
||||
})
|
||||
}
|
||||
else if(distribution.tag === "Discrete"){
|
||||
return Ok({
|
||||
discrete: shapePoints(distribution.value),
|
||||
continuous: []
|
||||
})
|
||||
}
|
||||
else if(distribution.tag === "Mixed"){
|
||||
return Ok({
|
||||
discrete: shapePoints(distribution.value.discrete),
|
||||
continuous: shapePoints(distribution.value.continuous)
|
||||
})
|
||||
}
|
||||
}
|
||||
else {
|
||||
return pointSet
|
||||
}
|
||||
}
|
||||
|
||||
toPointSet(): result<Distribution, distributionError> {
|
||||
return this.mapResultDist(
|
||||
Constructors_toPointSet({ env: this.env }, this.t)
|
||||
|
@ -170,8 +207,14 @@ export class Distribution {
|
|||
return this.mapResultDist(Constructors_inspect({ env: this.env }, this.t));
|
||||
}
|
||||
|
||||
toString(): result<string, distributionError> {
|
||||
return Constructors_toString({ env: this.env }, this.t);
|
||||
toString(): string {
|
||||
let result = Constructors_toString({ env: this.env }, this.t);
|
||||
if(result.tag === "Ok"){
|
||||
result.value
|
||||
}
|
||||
else {
|
||||
return distributionErrorToString(result.value)
|
||||
}
|
||||
}
|
||||
|
||||
toSparkline(n: number): result<string, distributionError> {
|
||||
|
|
|
@ -21,6 +21,7 @@ let toFloatOperation: (
|
|||
~distToFloatOperation: Operation.distToFloatOperation,
|
||||
) => result<float, error>
|
||||
|
||||
@genType
|
||||
let toPointSet: (
|
||||
t,
|
||||
~xyPointLength: int,
|
||||
|
|
|
@ -10,11 +10,22 @@ type error =
|
|||
| DistributionVerticalShiftIsInvalid
|
||||
| Other(string)
|
||||
|
||||
@genType
|
||||
module Error = {
|
||||
type t = error
|
||||
|
||||
let fromString = (s: string): t => Other(s)
|
||||
|
||||
@genType
|
||||
let toString = (x: t) => {
|
||||
switch x {
|
||||
| NotYetImplemented => "Not Yet Implemented"
|
||||
| Unreachable => "Unreachable"
|
||||
| DistributionVerticalShiftIsInvalid => "Distribution Vertical Shift Is Invalid"
|
||||
| Other(s) => s
|
||||
}
|
||||
}
|
||||
|
||||
let resultStringToResultError: result<'a, string> => result<'a, error> = n =>
|
||||
n->E.R2.errMap(r => r->fromString->Error)
|
||||
}
|
||||
|
@ -51,6 +62,7 @@ module Operation = {
|
|||
| #Sample
|
||||
]
|
||||
|
||||
@genType
|
||||
type pointsetXSelection = [#Linear | #ByWeight]
|
||||
|
||||
type toDist =
|
||||
|
|
|
@ -19,6 +19,7 @@ type interpolationStrategy = XYShape.interpolationStrategy;
|
|||
type extrapolationStrategy = XYShape.extrapolationStrategy;
|
||||
type interpolator = XYShape.extrapolationStrategy;
|
||||
|
||||
@genType
|
||||
type rec continuousShape = {
|
||||
xyShape: xyShape,
|
||||
interpolation: interpolationStrategy,
|
||||
|
@ -26,12 +27,14 @@ type rec continuousShape = {
|
|||
integralCache: option<continuousShape>,
|
||||
}
|
||||
|
||||
@genType
|
||||
type discreteShape = {
|
||||
xyShape: xyShape,
|
||||
integralSumCache: option<float>,
|
||||
integralCache: option<continuousShape>,
|
||||
}
|
||||
|
||||
@genType
|
||||
type mixedShape = {
|
||||
continuous: continuousShape,
|
||||
discrete: discreteShape,
|
||||
|
|
|
@ -8,6 +8,7 @@ type errorValue =
|
|||
|
||||
type t = errorValue
|
||||
|
||||
@genType
|
||||
let errorToString = err =>
|
||||
switch err {
|
||||
| REArrayIndexNotFound(msg, index) => `${msg}: ${Js.String.make(index)}`
|
||||
|
|
|
@ -36,3 +36,21 @@ type expressionValue = Reducer_Expression.expressionValue
|
|||
|
||||
@genType
|
||||
type errorValue = Reducer_ErrorValue.errorValue
|
||||
|
||||
@genType
|
||||
let toPointSet = GenericDist.toPointSet
|
||||
|
||||
@genType
|
||||
type mixedShape = PointSetTypes.mixedShape
|
||||
|
||||
@genType
|
||||
type discreteShape = PointSetTypes.discreteShape
|
||||
|
||||
@genType
|
||||
type continuousShape = PointSetTypes.continuousShape
|
||||
|
||||
@genType
|
||||
let errorValueToString = Reducer_ErrorValue.errorToString
|
||||
|
||||
@genType
|
||||
let distributionErrorToString = GenericDist_Types.Error.toString
|
||||
|
|
Loading…
Reference in New Issue
Block a user