From 282fa7726b7c5ff906a9fa1062faa7bfb2fcedb9 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Thu, 28 Apr 2022 21:14:03 -0400 Subject: [PATCH 01/26] Added scalePower and scaleLog --- .../DistributionOperation.res | 10 ++++++++++ .../Distributions/DistributionTypes.res | 10 ++++++++++ .../Distributions/GenericDist/GenericDist.res | 1 + .../Distributions/PointSetDist/Continuous.res | 6 ++++-- .../Distributions/PointSetDist/Discrete.res | 17 ++++++++++++----- .../Distributions/PointSetDist/Mixed.res | 9 ++++++--- .../Distributions/PointSetDist/PointSetDist.res | 7 ++++++- .../ReducerInterface_GenericDistribution.res | 9 +++++++++ 8 files changed, 58 insertions(+), 11 deletions(-) diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res index 18ee2d6a..91910824 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res @@ -154,6 +154,16 @@ let rec run = (~env, functionCallInfo: functionCallInfo): outputType => { ->GenericDist.toPointSet(~xyPointLength, ~sampleCount, ()) ->E.R2.fmap(r => Dist(PointSet(r))) ->OutputLocal.fromResult + | ToDist(Scale(#Logarithm, f)) => + dist + ->GenericDist.pointwiseCombinationFloat(~toPointSetFn, ~algebraicCombination=#Logarithm, ~f) + ->E.R2.fmap(r => Dist(r)) + ->OutputLocal.fromResult + | ToDist(Scale(#Power, f)) => + dist + ->GenericDist.pointwiseCombinationFloat(~toPointSetFn, ~algebraicCombination=#Power, ~f) + ->E.R2.fmap(r => Dist(r)) + ->OutputLocal.fromResult | ToDistCombination(Algebraic(_), _, #Float(_)) => GenDistError(NotYetImplemented) | ToDistCombination(Algebraic(strategy), arithmeticOperation, #Dist(t2)) => dist diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res b/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res index 93f86798..e970505d 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res @@ -70,10 +70,16 @@ module DistributionOperation = { | #Sample ] + type toScaleFn = [ + | #Power + | #Logarithm + ] + type toDist = | Normalize | ToPointSet | ToSampleSet(int) + | Scale(toScaleFn, float) | Truncate(option, option) | Inspect @@ -113,6 +119,8 @@ module DistributionOperation = { | ToDist(ToSampleSet(r)) => `toSampleSet(${E.I.toString(r)})` | ToDist(Truncate(_, _)) => `truncate` | ToDist(Inspect) => `inspect` + | ToDist(Scale(#Power, r)) => `scalePower(${E.Float.toFixed(r)})` + | ToDist(Scale(#Logarithm, r)) => `scaleLog(${E.Float.toFixed(r)})` | ToString(ToString) => `toString` | ToString(ToSparkline(n)) => `toSparkline(${E.I.toString(n)})` | ToBool(IsNormalized) => `isNormalized` @@ -142,6 +150,8 @@ module Constructors = { let toSampleSet = (dist, r): t => FromDist(ToDist(ToSampleSet(r)), dist) let truncate = (dist, left, right): t => FromDist(ToDist(Truncate(left, right)), dist) let inspect = (dist): t => FromDist(ToDist(Inspect), dist) + let scalePower = (dist, n): t => FromDist(ToDist(Scale(#Power, n)), dist) + let scaleLogarithm = (dist, n): t => FromDist(ToDist(Scale(#Logarithm, n)), dist) let toString = (dist): t => FromDist(ToString(ToString), dist) let toSparkline = (dist, n): t => FromDist(ToString(ToSparkline(n)), dist) let algebraicAdd = (dist1, dist2: genericDist): t => FromDist( diff --git a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.res b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.res index c19bdf7f..25b83bd3 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.res +++ b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.res @@ -366,6 +366,7 @@ let pointwiseCombination = ( ~algebraicCombination: Operation.algebraicOperation, ~t2: t, ): result => { + Js.log2("PointwiseCombination", algebraicCombination); E.R.merge(toPointSetFn(t1), toPointSetFn(t2))->E.R.bind(((t1, t2)) => PointSetDist.combinePointwise(Operation.Algebraic.toFn(algebraicCombination), t1, t2) ->E.R2.fmap(r => DistributionTypes.PointSet(r)) diff --git a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Continuous.res b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Continuous.res index d4286387..105b5a05 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Continuous.res +++ b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Continuous.res @@ -156,8 +156,10 @@ let reduce = ( ~integralSumCachesFn: (float, float) => option=(_, _) => None, fn: (float, float) => result, continuousShapes, -): result => - continuousShapes |> E.A.R.foldM(combinePointwise(~integralSumCachesFn, fn), empty) +): result => { + let merge = combinePointwise(~integralSumCachesFn, fn) + continuousShapes |> E.A.R.foldM(merge, empty) +} let mapYResult = ( ~integralSumCacheFn=_ => None, diff --git a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Discrete.res b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Discrete.res index fdc921c6..1149df7e 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Discrete.res +++ b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Discrete.res @@ -34,9 +34,10 @@ let lastY = (t: t) => t |> getShape |> XYShape.T.lastY let combinePointwise = ( ~integralSumCachesFn=(_, _) => None, + fn, t1: PointSetTypes.discreteShape, t2: PointSetTypes.discreteShape, -): PointSetTypes.discreteShape => { +): result => { let combinedIntegralSum = Common.combineIntegralSums( integralSumCachesFn, t1.integralSumCache, @@ -49,16 +50,22 @@ let combinePointwise = ( make( ~integralSumCache=combinedIntegralSum, XYShape.PointwiseCombination.combine( - (a, b) => Ok(a +. b), + fn, XYShape.XtoY.discreteInterpolator, t1.xyShape, t2.xyShape, )->E.R.toExn("Addition operation should never fail", _), - ) + )->Ok } -let reduce = (~integralSumCachesFn=(_, _) => None, discreteShapes): PointSetTypes.discreteShape => - discreteShapes |> E.A.fold_left(combinePointwise(~integralSumCachesFn), empty) +let reduce = ( + ~integralSumCachesFn=(_, _) => None, + fn: (float, float) => result, + discreteShapes: array, +): result => { + let merge = combinePointwise(~integralSumCachesFn, fn) + discreteShapes |> E.A.R.foldM(merge, empty) +} let updateIntegralSumCache = (integralSumCache, t: t): t => { ...t, diff --git a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Mixed.res b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Mixed.res index 4ce2bdd6..98e7923a 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Mixed.res +++ b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Mixed.res @@ -316,7 +316,10 @@ let combinePointwise = ( t2: t, ): result => { let reducedDiscrete = - [t1, t2] |> E.A.fmap(toDiscrete) |> E.A.O.concatSomes |> Discrete.reduce(~integralSumCachesFn) + [t1, t2] + |> E.A.fmap(toDiscrete) + |> E.A.O.concatSomes + |> Discrete.reduce(~integralSumCachesFn, fn) let reducedContinuous = [t1, t2] @@ -335,11 +338,11 @@ let combinePointwise = ( t1.integralCache, t2.integralCache, ) - reducedContinuous->E.R2.fmap(continuous => + E.R.merge(reducedContinuous, reducedDiscrete)->E.R2.fmap(((continuous, discrete)) => make( ~integralSumCache=combinedIntegralSum, ~integralCache=combinedIntegral, - ~discrete=reducedDiscrete, + ~discrete, ~continuous, ) ) diff --git a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/PointSetDist.res b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/PointSetDist.res index 12aa5477..00c900dc 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/PointSetDist.res +++ b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/PointSetDist.res @@ -84,7 +84,12 @@ let combinePointwise = ( m2, )->E.R2.fmap(x => PointSetTypes.Continuous(x)) | (Discrete(m1), Discrete(m2)) => - Ok(PointSetTypes.Discrete(Discrete.combinePointwise(~integralSumCachesFn, m1, m2))) + Discrete.combinePointwise( + ~integralSumCachesFn, + fn, + m1, + m2, + )->E.R2.fmap(x => PointSetTypes.Discrete(x)) | (m1, m2) => Mixed.combinePointwise( ~integralSumCachesFn, diff --git a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res index ab76f469..f69ff8b5 100644 --- a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res @@ -211,6 +211,15 @@ let dispatchToGenericOutput = (call: ExpressionValue.functionCall): option< | ("normalize", [EvDistribution(dist)]) => Helpers.toDistFn(Normalize, dist) | ("isNormalized", [EvDistribution(dist)]) => Helpers.toBoolFn(IsNormalized, dist) | ("toPointSet", [EvDistribution(dist)]) => Helpers.toDistFn(ToPointSet, dist) + | ("scaleLog", [EvDistribution(dist)]) => + Helpers.toDistFn(Scale(#Logarithm, MagicNumbers.Math.e), dist) + | ("scaleLog10", [EvDistribution(dist)]) => Helpers.toDistFn(Scale(#Logarithm, 10.0), dist) + | ("scaleLog", [EvDistribution(dist), EvNumber(float)]) => + Helpers.toDistFn(Scale(#Logarithm, float), dist) + | ("scalePow", [EvDistribution(dist), EvNumber(float)]) => + Helpers.toDistFn(Scale(#Power, float), dist) + | ("scaleExp", [EvDistribution(dist)]) => + Helpers.toDistFn(Scale(#Power, MagicNumbers.Math.e), dist) | ("cdf", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Cdf(float), dist) | ("pdf", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Pdf(float), dist) | ("inv", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Inv(float), dist) From 900aeeae29ea6fad0f7efb7594ac4f4445ff633e Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Thu, 28 Apr 2022 21:31:15 -0400 Subject: [PATCH 02/26] Expose integralSum to Squiggle --- .../Distributions/DistributionTypes.res | 1 + .../Distributions/GenericDist/GenericDist.res | 40 ++++++++++--------- .../GenericDist/GenericDist.resi | 2 +- .../ReducerInterface_GenericDistribution.res | 1 + 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res b/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res index e970505d..255819d1 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res @@ -68,6 +68,7 @@ module DistributionOperation = { | #Pdf(float) | #Mean | #Sample + | #IntegralSum ] type toScaleFn = [ diff --git a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.res b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.res index 25b83bd3..160ce640 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.res +++ b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.res @@ -62,26 +62,31 @@ let isNormalized = (t: t): bool => Js.Math.abs_float(integralEndY(t) -. 1.0) < 1 let toFloatOperation = ( t, ~toPointSetFn: toPointSetFn, - ~distToFloatOperation: Operation.distToFloatOperation, + ~distToFloatOperation: DistributionTypes.DistributionOperation.toFloat, ) => { - let trySymbolicSolution = switch (t: t) { - | Symbolic(r) => SymbolicDist.T.operate(distToFloatOperation, r)->E.R.toOption - | _ => None - } + switch distToFloatOperation { + | #IntegralSum => Ok(integralEndY(t)) + | (#Pdf(_) | #Cdf(_) | #Inv(_) | #Mean | #Sample) as op => { + let trySymbolicSolution = switch (t: t) { + | Symbolic(r) => SymbolicDist.T.operate(op, r)->E.R.toOption + | _ => None + } - let trySampleSetSolution = switch ((t: t), distToFloatOperation) { - | (SampleSet(sampleSet), #Mean) => SampleSetDist.mean(sampleSet)->Some - | (SampleSet(sampleSet), #Sample) => SampleSetDist.sample(sampleSet)->Some - | (SampleSet(sampleSet), #Inv(r)) => SampleSetDist.percentile(sampleSet, r)->Some - | _ => None - } + let trySampleSetSolution = switch ((t: t), distToFloatOperation) { + | (SampleSet(sampleSet), #Mean) => SampleSetDist.mean(sampleSet)->Some + | (SampleSet(sampleSet), #Sample) => SampleSetDist.sample(sampleSet)->Some + | (SampleSet(sampleSet), #Inv(r)) => SampleSetDist.percentile(sampleSet, r)->Some + | _ => None + } - switch trySymbolicSolution { - | Some(r) => Ok(r) - | None => - switch trySampleSetSolution { - | Some(r) => Ok(r) - | None => toPointSetFn(t)->E.R2.fmap(PointSetDist.operate(distToFloatOperation)) + switch trySymbolicSolution { + | Some(r) => Ok(r) + | None => + switch trySampleSetSolution { + | Some(r) => Ok(r) + | None => toPointSetFn(t)->E.R2.fmap(PointSetDist.operate(op)) + } + } } } } @@ -366,7 +371,6 @@ let pointwiseCombination = ( ~algebraicCombination: Operation.algebraicOperation, ~t2: t, ): result => { - Js.log2("PointwiseCombination", algebraicCombination); E.R.merge(toPointSetFn(t1), toPointSetFn(t2))->E.R.bind(((t1, t2)) => PointSetDist.combinePointwise(Operation.Algebraic.toFn(algebraicCombination), t1, t2) ->E.R2.fmap(r => DistributionTypes.PointSet(r)) diff --git a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.resi b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.resi index e91803e2..3d143edc 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.resi +++ b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.resi @@ -20,7 +20,7 @@ let isNormalized: t => bool let toFloatOperation: ( t, ~toPointSetFn: toPointSetFn, - ~distToFloatOperation: Operation.distToFloatOperation, + ~distToFloatOperation: DistributionTypes.DistributionOperation.toFloat, ) => result @genType diff --git a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res index f69ff8b5..a53425e8 100644 --- a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res @@ -196,6 +196,7 @@ let dispatchToGenericOutput = (call: ExpressionValue.functionCall): option< ->SymbolicConstructors.symbolicResultToOutput | ("sample", [EvDistribution(dist)]) => Helpers.toFloatFn(#Sample, dist) | ("mean", [EvDistribution(dist)]) => Helpers.toFloatFn(#Mean, dist) + | ("integralSum", [EvDistribution(dist)]) => Helpers.toFloatFn(#IntegralSum, dist) | ("toString", [EvDistribution(dist)]) => Helpers.toStringFn(ToString, dist) | ("toSparkline", [EvDistribution(dist)]) => Helpers.toStringFn(ToSparkline(20), dist) | ("toSparkline", [EvDistribution(dist), EvNumber(n)]) => From d4f929367d4a9d098d6694ff6cec63078481e649 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Fri, 29 Apr 2022 18:46:44 +0000 Subject: [PATCH 03/26] JS parameters in squiggle lang --- packages/components/package.json | 35 ++++++------ .../squiggle-lang/__tests__/TS/JS_test.ts | 23 ++++++++ .../squiggle-lang/__tests__/TS/TestHelpers.ts | 38 +++++++++---- packages/squiggle-lang/src/js/index.ts | 56 +++++++++++++++++-- .../Reducer_MathJs/Reducer_MathJs_Eval.res | 1 + 5 files changed, 120 insertions(+), 33 deletions(-) diff --git a/packages/components/package.json b/packages/components/package.json index de8efb96..3b50afbf 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,19 +1,19 @@ { "name": "@quri/squiggle-components", - "version": "0.2.14", + "version": "0.2.15", "license": "MIT", "dependencies": { - "react-ace": "10.1.0", "@quri/squiggle-lang": "^0.2.7", - "react-dom": "^18.1.0", - "vega": "^5.22.1", - "vega-embed": "^6.20.6", - "vega-lite": "^5.2.0", - "react-vega": "^7.5.0", - "react": "^18.1.0", "@react-hook/size": "^2.1.2", "lodash": "^4.17.21", - "styled-components": "^5.3.5" + "react": "^18.1.0", + "react-ace": "10.1.0", + "react-dom": "^18.1.0", + "react-vega": "^7.5.0", + "styled-components": "^5.3.5", + "vega": "^5.22.1", + "vega-embed": "^6.20.6", + "vega-lite": "^5.2.0" }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.16.7", @@ -25,27 +25,26 @@ "@storybook/node-logger": "^6.4.22", "@storybook/preset-create-react-app": "^4.1.0", "@storybook/react": "^6.4.22", - "@types/styled-components": "^5.1.24", - "@types/webpack": "^5.28.0", - "style-loader": "^3.3.1", - "ts-loader": "^9.2.9", - "webpack": "^5.72.0", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.8.1", "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^13.1.1", "@testing-library/user-event": "^14.1.1", "@types/jest": "^27.4.0", - "web-vitals": "^2.1.4", "@types/lodash": "^4.14.182", "@types/node": "^17.0.29", "@types/react": "^18.0.3", "@types/react-dom": "^18.0.2", + "@types/styled-components": "^5.1.24", + "@types/webpack": "^5.28.0", "cross-env": "^7.0.3", "react-scripts": "5.0.1", + "style-loader": "^3.3.1", + "ts-loader": "^9.2.9", "tsconfig-paths-webpack-plugin": "^3.5.2", "typescript": "^4.6.3", - "webpack-cli": "^4.9.2" + "web-vitals": "^2.1.4", + "webpack": "^5.72.0", + "webpack-cli": "^4.9.2", + "webpack-dev-server": "^4.8.1" }, "scripts": { "start": "cross-env REACT_APP_FAST_REFRESH=false && start-storybook -p 6006 -s public", diff --git a/packages/squiggle-lang/__tests__/TS/JS_test.ts b/packages/squiggle-lang/__tests__/TS/JS_test.ts index e522eb95..62051261 100644 --- a/packages/squiggle-lang/__tests__/TS/JS_test.ts +++ b/packages/squiggle-lang/__tests__/TS/JS_test.ts @@ -68,6 +68,29 @@ describe("Partials", () => { }); }); +describe("Parameters", () => { + test("Can pass parameters into partials and cells", () => { + let bindings = testRunPartial(`y = $x + 2`, {}, { x: 1 }); // y = 3 + let bindings2 = testRunPartial(`z = $x + y * $a`, bindings, { a: 3 }); // z = 1 + 3 * 3 = 10 + expect(testRun(`z + $x + $a + y`, bindings2)).toEqual({ + tag: "number", + value: 17, + }); + }); + test("Complicated deep parameters", () => { + expect( + testRun( + `$x.y[0][0].w + $x.z + $u.v`, + {}, + { x: { y: [[{ w: 1 }]], z: 2 }, u: { v: 3 } } + ) + ).toEqual({ + tag: "number", + value: 6, + }); + }); +}); + describe("Distribution", () => { //It's important that sampleCount is less than 9. If it's more, than that will create randomness //Also, note, the value should be created using makeSampleSetDist() later on. diff --git a/packages/squiggle-lang/__tests__/TS/TestHelpers.ts b/packages/squiggle-lang/__tests__/TS/TestHelpers.ts index 7d51c98e..3bbf42d8 100644 --- a/packages/squiggle-lang/__tests__/TS/TestHelpers.ts +++ b/packages/squiggle-lang/__tests__/TS/TestHelpers.ts @@ -6,11 +6,20 @@ import { errorValueToString, } from "../../src/js/index"; -export function testRun(x: string, bindings = {}): squiggleExpression { - let squiggleResult = run(x, bindings, { - sampleCount: 1000, - xyPointLength: 100, - }); +export function testRun( + x: string, + bindings = {}, + parameters = {} +): squiggleExpression { + let squiggleResult = run( + x, + bindings, + { + sampleCount: 1000, + xyPointLength: 100, + }, + parameters + ); // return squiggleResult.value if (squiggleResult.tag === "Ok") { return squiggleResult.value; @@ -23,11 +32,20 @@ export function testRun(x: string, bindings = {}): squiggleExpression { } } -export function testRunPartial(x: string, bindings: bindings = {}): bindings { - let squiggleResult = runPartial(x, bindings, { - sampleCount: 1000, - xyPointLength: 100, - }); +export function testRunPartial( + x: string, + bindings: bindings = {}, + parameters = {} +): bindings { + let squiggleResult = runPartial( + x, + bindings, + { + sampleCount: 1000, + xyPointLength: 100, + }, + parameters + ); if (squiggleResult.tag === "Ok") { return squiggleResult.value; } else { diff --git a/packages/squiggle-lang/src/js/index.ts b/packages/squiggle-lang/src/js/index.ts index fb67e47a..cd63c922 100644 --- a/packages/squiggle-lang/src/js/index.ts +++ b/packages/squiggle-lang/src/js/index.ts @@ -99,25 +99,71 @@ export type squiggleExpression = export function run( squiggleString: string, bindings?: externalBindings, - samplingInputs?: samplingParams + samplingInputs?: samplingParams, + parameters?: parameters ): result { let b = bindings ? bindings : {}; + let p = parameters ? parameters : {}; let si: samplingParams = samplingInputs ? samplingInputs : defaultSamplingInputs; let result: result = - evaluateUsingExternalBindings(squiggleString, b); + evaluateUsingExternalBindings(squiggleString, mergeParameters(b, p)); return resultMap(result, (x) => createTsExport(x, si)); } // Run Partial. A partial is a block of code that doesn't return a value export function runPartial( squiggleString: string, - bindings: externalBindings, - _samplingInputs?: samplingParams + bindings?: externalBindings, + _samplingInputs?: samplingParams, + parameters?: parameters ): result { - return evaluatePartialUsingExternalBindings(squiggleString, bindings); + let b = bindings ? bindings : {}; + let p = parameters ? parameters : {}; + + return evaluatePartialUsingExternalBindings( + squiggleString, + mergeParameters(b, p) + ); +} + +function mergeParameters( + bindings: externalBindings, + parameters: parameters +): externalBindings { + let transformedParemeters = Object.fromEntries( + Object.entries(parameters).map(([key, value]) => [ + "$" + key, + jsValueToBinding(value), + ]) + ); + return _.merge(bindings, transformedParemeters); +} + +type parameters = { [key: string]: jsValue }; + +type jsValue = + | string + | number + | jsValue[] + | { [key: string]: jsValue } + | boolean; + +function jsValueToBinding(value: jsValue): rescriptExport { + if (typeof value === "boolean") { + return { TAG: 1, _0: value as boolean }; + } else if (typeof value === "string") { + return { TAG: 6, _0: value as string }; + } else if (typeof value === "number") { + return { TAG: 4, _0: value as number }; + } else if (Array.isArray(value)) { + return { TAG: 0, _0: value.map(jsValueToBinding) }; + } else { + // Record + return { TAG: 5, _0: _.mapValues(value, jsValueToBinding) }; + } } function createTsExport( diff --git a/packages/squiggle-lang/src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_Eval.res b/packages/squiggle-lang/src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_Eval.res index ab9fb711..86a7a593 100644 --- a/packages/squiggle-lang/src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_Eval.res +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_Eval.res @@ -19,6 +19,7 @@ let eval__: string => 'a = %raw(`function (expr) { return {value: Mathjs.evaluat */ let eval = (expr: string): result => { try { + Js.log(expr) let answer = eval__(expr) answer["value"]->JavaScript.Gate.jsToEv } catch { From 39be07cac0d7136d74078beba0097da79da74665 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Fri, 29 Apr 2022 19:02:43 +0000 Subject: [PATCH 04/26] Add parameters to components interface --- .../src/components/SquiggleChart.tsx | 17 +++++++++--- .../src/components/SquiggleEditor.tsx | 26 +++++++++++++++---- packages/squiggle-lang/src/js/index.ts | 18 +++++++++---- 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/packages/components/src/components/SquiggleChart.tsx b/packages/components/src/components/SquiggleChart.tsx index 8730beaa..235a4cee 100644 --- a/packages/components/src/components/SquiggleChart.tsx +++ b/packages/components/src/components/SquiggleChart.tsx @@ -3,16 +3,17 @@ import _ from "lodash"; import styled from "styled-components"; import { run, - runPartial, errorValueToString, squiggleExpression, bindings, samplingParams, + parameters, + defaultParameters, + defaultBindings, } from "@quri/squiggle-lang"; import { NumberShower } from "./NumberShower"; import { DistributionChart } from "./DistributionChart"; import { ErrorBox } from "./ErrorBox"; -import useSize from "@react-hook/size"; const variableBox = { Component: styled.div` @@ -152,6 +153,8 @@ export interface SquiggleChartProps { height?: number; /** Bindings of previous variables declared */ bindings?: bindings; + /** JS imported parameters */ + parameters?: parameters; } const ChartWrapper = styled.div` @@ -166,14 +169,20 @@ export const SquiggleChart: React.FC = ({ outputXYPoints = 1000, onChange = () => {}, height = 60, - bindings = {}, + bindings = defaultBindings, + parameters = defaultParameters, width = NaN, }: SquiggleChartProps) => { let samplingInputs: samplingParams = { sampleCount: sampleCount, xyPointLength: outputXYPoints, }; - let expressionResult = run(squiggleString, bindings, samplingInputs); + let expressionResult = run( + squiggleString, + bindings, + samplingInputs, + parameters + ); let internal: JSX.Element; if (expressionResult.tag === "Ok") { let expression = expressionResult.value; diff --git a/packages/components/src/components/SquiggleEditor.tsx b/packages/components/src/components/SquiggleEditor.tsx index f85cf1e8..67f2e73b 100644 --- a/packages/components/src/components/SquiggleEditor.tsx +++ b/packages/components/src/components/SquiggleEditor.tsx @@ -3,8 +3,17 @@ import * as ReactDOM from "react-dom"; import { SquiggleChart } from "./SquiggleChart"; import { CodeEditor } from "./CodeEditor"; import styled from "styled-components"; -import type { squiggleExpression, bindings } from "@quri/squiggle-lang"; -import { runPartial, errorValueToString } from "@quri/squiggle-lang"; +import type { + squiggleExpression, + bindings, + parameters, +} from "@quri/squiggle-lang"; +import { + runPartial, + errorValueToString, + defaultParameters, + defaultBindings, +} from "@quri/squiggle-lang"; import { ErrorBox } from "./ErrorBox"; export interface SquiggleEditorProps { @@ -30,6 +39,8 @@ export interface SquiggleEditorProps { width: number; /** Previous variable declarations */ bindings: bindings; + /** JS Imported parameters */ + parameters: parameters; } const Input = styled.div` @@ -50,7 +61,8 @@ export let SquiggleEditor: React.FC = ({ diagramCount, onChange, environment, - bindings = {}, + bindings = defaultBindings, + parameters = defaultParameters, }: SquiggleEditorProps) => { let [expression, setExpression] = React.useState(initialSquiggleString); return ( @@ -77,6 +89,7 @@ export let SquiggleEditor: React.FC = ({ environment={environment} onChange={onChange} bindings={bindings} + parameters={parameters} /> ); @@ -134,13 +147,16 @@ export interface SquigglePartialProps { /** The width of the element */ width: number; /** Previously declared variables */ - bindings: bindings; + bindings?: bindings; + /** Parameters imported from js */ + parameters?: parameters; } export let SquigglePartial: React.FC = ({ initialSquiggleString = "", onChange, - bindings, + bindings = defaultBindings, + parameters = defaultParameters, }: SquigglePartialProps) => { let [expression, setExpression] = React.useState(initialSquiggleString); let squiggleResult = runPartial(expression, bindings); diff --git a/packages/squiggle-lang/src/js/index.ts b/packages/squiggle-lang/src/js/index.ts index cd63c922..1c0fb4e3 100644 --- a/packages/squiggle-lang/src/js/index.ts +++ b/packages/squiggle-lang/src/js/index.ts @@ -48,7 +48,12 @@ import { Constructors_pointwiseLogarithm, Constructors_pointwisePower, } from "../rescript/Distributions/DistributionOperation/DistributionOperation.gen"; -export type { samplingParams, errorValue, externalBindings as bindings }; +export type { + samplingParams, + errorValue, + externalBindings as bindings, + parameters, +}; export let defaultSamplingInputs: samplingParams = { sampleCount: 10000, @@ -102,8 +107,8 @@ export function run( samplingInputs?: samplingParams, parameters?: parameters ): result { - let b = bindings ? bindings : {}; - let p = parameters ? parameters : {}; + let b = bindings ? bindings : defaultBindings; + let p = parameters ? parameters : defaultParameters; let si: samplingParams = samplingInputs ? samplingInputs : defaultSamplingInputs; @@ -120,8 +125,8 @@ export function runPartial( _samplingInputs?: samplingParams, parameters?: parameters ): result { - let b = bindings ? bindings : {}; - let p = parameters ? parameters : {}; + let b = bindings ? bindings : defaultBindings; + let p = parameters ? parameters : defaultParameters; return evaluatePartialUsingExternalBindings( squiggleString, @@ -144,6 +149,9 @@ function mergeParameters( type parameters = { [key: string]: jsValue }; +export let defaultParameters: parameters = {}; +export let defaultBindings: externalBindings = {}; + type jsValue = | string | number From 237cdf12f9f925324af99a3f215dc46e03990895 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Fri, 29 Apr 2022 19:13:30 +0000 Subject: [PATCH 05/26] Remove accidental log --- .../src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_Eval.res | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/squiggle-lang/src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_Eval.res b/packages/squiggle-lang/src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_Eval.res index 86a7a593..ab9fb711 100644 --- a/packages/squiggle-lang/src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_Eval.res +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_Eval.res @@ -19,7 +19,6 @@ let eval__: string => 'a = %raw(`function (expr) { return {value: Mathjs.evaluat */ let eval = (expr: string): result => { try { - Js.log(expr) let answer = eval__(expr) answer["value"]->JavaScript.Gate.jsToEv } catch { From 74df093a42539f3255577a9cce54ccd8b7371860 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Fri, 29 Apr 2022 20:10:39 +0000 Subject: [PATCH 06/26] Cleanup TS code (and fix rescript build warning) --- .../squiggle-lang/__tests__/TS/JS_test.ts | 17 +- packages/squiggle-lang/src/js/distribution.ts | 247 ++++++++++ packages/squiggle-lang/src/js/index.ts | 439 +----------------- .../squiggle-lang/src/js/rescript_interop.ts | 155 +++++++ packages/squiggle-lang/src/js/types.ts | 30 ++ .../squiggle-lang/src/rescript/Utility/E.res | 2 +- 6 files changed, 454 insertions(+), 436 deletions(-) create mode 100644 packages/squiggle-lang/src/js/distribution.ts create mode 100644 packages/squiggle-lang/src/js/rescript_interop.ts create mode 100644 packages/squiggle-lang/src/js/types.ts diff --git a/packages/squiggle-lang/__tests__/TS/JS_test.ts b/packages/squiggle-lang/__tests__/TS/JS_test.ts index 62051261..004d715e 100644 --- a/packages/squiggle-lang/__tests__/TS/JS_test.ts +++ b/packages/squiggle-lang/__tests__/TS/JS_test.ts @@ -1,4 +1,4 @@ -import { Distribution, resultMap } from "../../src/js/index"; +import { Distribution, resultMap, defaultBindings } from "../../src/js/index"; import { testRun, testRunPartial } from "./TestHelpers"; function Ok(x: b) { @@ -70,20 +70,19 @@ describe("Partials", () => { describe("Parameters", () => { test("Can pass parameters into partials and cells", () => { - let bindings = testRunPartial(`y = $x + 2`, {}, { x: 1 }); // y = 3 - let bindings2 = testRunPartial(`z = $x + y * $a`, bindings, { a: 3 }); // z = 1 + 3 * 3 = 10 - expect(testRun(`z + $x + $a + y`, bindings2)).toEqual({ + let bindings = testRunPartial(`y = $x + 2`, defaultBindings, { x: 1 }); + let bindings2 = testRunPartial(`z = y + $a`, bindings, { a: 3 }); + expect(testRun(`z`, bindings2)).toEqual({ tag: "number", value: 17, }); }); test("Complicated deep parameters", () => { expect( - testRun( - `$x.y[0][0].w + $x.z + $u.v`, - {}, - { x: { y: [[{ w: 1 }]], z: 2 }, u: { v: 3 } } - ) + testRun(`$x.y[0][0].w + $x.z + $u.v`, defaultBindings, { + x: { y: [[{ w: 1 }]], z: 2 }, + u: { v: 3 }, + }) ).toEqual({ tag: "number", value: 6, diff --git a/packages/squiggle-lang/src/js/distribution.ts b/packages/squiggle-lang/src/js/distribution.ts new file mode 100644 index 00000000..603dfaa9 --- /dev/null +++ b/packages/squiggle-lang/src/js/distribution.ts @@ -0,0 +1,247 @@ +import * as _ from "lodash"; +import { + genericDist, + continuousShape, + discreteShape, + samplingParams, + distributionError, + toPointSet, + distributionErrorToString, +} from "../rescript/TypescriptInterface.gen"; +import { result, resultMap, Ok } from "./types"; +import { + Constructors_mean, + Constructors_sample, + Constructors_pdf, + Constructors_cdf, + Constructors_inv, + Constructors_normalize, + Constructors_isNormalized, + Constructors_toPointSet, + Constructors_toSampleSet, + Constructors_truncate, + Constructors_inspect, + Constructors_toString, + Constructors_toSparkline, + Constructors_algebraicAdd, + Constructors_algebraicMultiply, + Constructors_algebraicDivide, + Constructors_algebraicSubtract, + Constructors_algebraicLogarithm, + Constructors_algebraicPower, + Constructors_pointwiseAdd, + Constructors_pointwiseMultiply, + Constructors_pointwiseDivide, + Constructors_pointwiseSubtract, + Constructors_pointwiseLogarithm, + Constructors_pointwisePower, +} from "../rescript/Distributions/DistributionOperation/DistributionOperation.gen"; + +export type point = { x: number; y: number }; + +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 type shape = { + continuous: point[]; + discrete: point[]; +}; + +export class Distribution { + t: genericDist; + env: samplingParams; + + constructor(t: genericDist, env: samplingParams) { + this.t = t; + this.env = env; + return this; + } + + mapResultDist( + r: result + ): result { + return resultMap(r, (v: genericDist) => new Distribution(v, this.env)); + } + + mean(): result { + return Constructors_mean({ env: this.env }, this.t); + } + + sample(): result { + return Constructors_sample({ env: this.env }, this.t); + } + + pdf(n: number): result { + return Constructors_pdf({ env: this.env }, this.t, n); + } + + cdf(n: number): result { + return Constructors_cdf({ env: this.env }, this.t, n); + } + + inv(n: number): result { + return Constructors_inv({ env: this.env }, this.t, n); + } + + isNormalized(): result { + return Constructors_isNormalized({ env: this.env }, this.t); + } + + normalize(): result { + return this.mapResultDist( + Constructors_normalize({ env: this.env }, this.t) + ); + } + + type() { + return this.t.tag; + } + + pointSet(): result { + let pointSet = toPointSet( + this.t, + { + xyPointLength: this.env.xyPointLength, + sampleCount: this.env.sampleCount, + }, + undefined + ); + 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 { + return Ok({ + discrete: shapePoints(distribution.value.discrete), + continuous: shapePoints(distribution.value.continuous), + }); + } + } else { + return pointSet; + } + } + + toPointSet(): result { + return this.mapResultDist( + Constructors_toPointSet({ env: this.env }, this.t) + ); + } + + toSampleSet(n: number): result { + return this.mapResultDist( + Constructors_toSampleSet({ env: this.env }, this.t, n) + ); + } + + truncate( + left: number, + right: number + ): result { + return this.mapResultDist( + Constructors_truncate({ env: this.env }, this.t, left, right) + ); + } + + inspect(): result { + return this.mapResultDist(Constructors_inspect({ env: this.env }, this.t)); + } + + toString(): string { + let result = Constructors_toString({ env: this.env }, this.t); + if (result.tag === "Ok") { + return result.value; + } else { + return distributionErrorToString(result.value); + } + } + + toSparkline(n: number): result { + return Constructors_toSparkline({ env: this.env }, this.t, n); + } + + algebraicAdd(d2: Distribution): result { + return this.mapResultDist( + Constructors_algebraicAdd({ env: this.env }, this.t, d2.t) + ); + } + + algebraicMultiply(d2: Distribution): result { + return this.mapResultDist( + Constructors_algebraicMultiply({ env: this.env }, this.t, d2.t) + ); + } + + algebraicDivide(d2: Distribution): result { + return this.mapResultDist( + Constructors_algebraicDivide({ env: this.env }, this.t, d2.t) + ); + } + + algebraicSubtract(d2: Distribution): result { + return this.mapResultDist( + Constructors_algebraicSubtract({ env: this.env }, this.t, d2.t) + ); + } + + algebraicLogarithm( + d2: Distribution + ): result { + return this.mapResultDist( + Constructors_algebraicLogarithm({ env: this.env }, this.t, d2.t) + ); + } + + algebraicPower(d2: Distribution): result { + return this.mapResultDist( + Constructors_algebraicPower({ env: this.env }, this.t, d2.t) + ); + } + + pointwiseAdd(d2: Distribution): result { + return this.mapResultDist( + Constructors_pointwiseAdd({ env: this.env }, this.t, d2.t) + ); + } + + pointwiseMultiply(d2: Distribution): result { + return this.mapResultDist( + Constructors_pointwiseMultiply({ env: this.env }, this.t, d2.t) + ); + } + + pointwiseDivide(d2: Distribution): result { + return this.mapResultDist( + Constructors_pointwiseDivide({ env: this.env }, this.t, d2.t) + ); + } + + pointwiseSubtract(d2: Distribution): result { + return this.mapResultDist( + Constructors_pointwiseSubtract({ env: this.env }, this.t, d2.t) + ); + } + + pointwiseLogarithm( + d2: Distribution + ): result { + return this.mapResultDist( + Constructors_pointwiseLogarithm({ env: this.env }, this.t, d2.t) + ); + } + + pointwisePower(d2: Distribution): result { + return this.mapResultDist( + Constructors_pointwisePower({ env: this.env }, this.t, d2.t) + ); + } +} diff --git a/packages/squiggle-lang/src/js/index.ts b/packages/squiggle-lang/src/js/index.ts index 1c0fb4e3..04d6050a 100644 --- a/packages/squiggle-lang/src/js/index.ts +++ b/packages/squiggle-lang/src/js/index.ts @@ -1,106 +1,40 @@ import * as _ from "lodash"; import { - genericDist, samplingParams, evaluateUsingExternalBindings, evaluatePartialUsingExternalBindings, externalBindings, expressionValue, errorValue, - distributionError, - toPointSet, - continuousShape, - discreteShape, - distributionErrorToString, - mixedShape, - sampleSetDist, - symbolicDist, } from "../rescript/TypescriptInterface.gen"; export { makeSampleSetDist, errorValueToString, distributionErrorToString, } from "../rescript/TypescriptInterface.gen"; -import { - Constructors_mean, - Constructors_sample, - Constructors_pdf, - Constructors_cdf, - Constructors_inv, - Constructors_normalize, - Constructors_isNormalized, - Constructors_toPointSet, - Constructors_toSampleSet, - Constructors_truncate, - Constructors_inspect, - Constructors_toString, - Constructors_toSparkline, - Constructors_algebraicAdd, - Constructors_algebraicMultiply, - Constructors_algebraicDivide, - Constructors_algebraicSubtract, - Constructors_algebraicLogarithm, - Constructors_algebraicPower, - Constructors_pointwiseAdd, - Constructors_pointwiseMultiply, - Constructors_pointwiseDivide, - Constructors_pointwiseSubtract, - Constructors_pointwiseLogarithm, - Constructors_pointwisePower, -} from "../rescript/Distributions/DistributionOperation/DistributionOperation.gen"; export type { samplingParams, errorValue, externalBindings as bindings, parameters, }; +import { + jsValueToBinding, + jsValue, + rescriptExport, + squiggleExpression, + convertRawToTypescript, +} from "./rescript_interop"; +import { result, resultMap, tag, tagged } from "./types"; +import { Distribution } from "./distribution"; + +export { Distribution, squiggleExpression, result }; export let defaultSamplingInputs: samplingParams = { sampleCount: 10000, xyPointLength: 10000, }; -export type result = - | { - tag: "Ok"; - value: a; - } - | { - tag: "Error"; - value: b; - }; - -export function resultMap( - r: result, - mapFn: (x: a) => b -): result { - if (r.tag === "Ok") { - return { tag: "Ok", value: mapFn(r.value) }; - } else { - return r; - } -} - -function Ok(x: a): result { - return { tag: "Ok", value: x }; -} - -type tagged = { tag: a; value: b }; - -function tag(x: a, y: b): tagged { - return { tag: x, value: y }; -} - -export type squiggleExpression = - | tagged<"symbol", string> - | tagged<"string", string> - | tagged<"call", string> - | tagged<"array", squiggleExpression[]> - | tagged<"boolean", boolean> - | tagged<"distribution", Distribution> - | tagged<"number", number> - | tagged<"record", { [key: string]: squiggleExpression }>; - export function run( squiggleString: string, bindings?: externalBindings, @@ -138,13 +72,13 @@ function mergeParameters( bindings: externalBindings, parameters: parameters ): externalBindings { - let transformedParemeters = Object.fromEntries( + let transformedParameters = Object.fromEntries( Object.entries(parameters).map(([key, value]) => [ "$" + key, jsValueToBinding(value), ]) ); - return _.merge(bindings, transformedParemeters); + return _.merge(bindings, transformedParameters); } type parameters = { [key: string]: jsValue }; @@ -152,28 +86,6 @@ type parameters = { [key: string]: jsValue }; export let defaultParameters: parameters = {}; export let defaultBindings: externalBindings = {}; -type jsValue = - | string - | number - | jsValue[] - | { [key: string]: jsValue } - | boolean; - -function jsValueToBinding(value: jsValue): rescriptExport { - if (typeof value === "boolean") { - return { TAG: 1, _0: value as boolean }; - } else if (typeof value === "string") { - return { TAG: 6, _0: value as string }; - } else if (typeof value === "number") { - return { TAG: 4, _0: value as number }; - } else if (Array.isArray(value)) { - return { TAG: 0, _0: value.map(jsValueToBinding) }; - } else { - // Record - return { TAG: 5, _0: _.mapValues(value, jsValueToBinding) }; - } -} - function createTsExport( x: expressionValue, sampEnv: samplingParams @@ -235,328 +147,3 @@ function createTsExport( } } -// Helper functions to convert the rescript representations that genType doesn't -// cover -function convertRawToTypescript( - result: rescriptExport, - sampEnv: samplingParams -): squiggleExpression { - switch (result.TAG) { - case 0: // EvArray - return tag( - "array", - result._0.map((x) => convertRawToTypescript(x, sampEnv)) - ); - case 1: // EvBool - return tag("boolean", result._0); - case 2: // EvCall - return tag("call", result._0); - case 3: // EvDistribution - return tag( - "distribution", - new Distribution( - convertRawDistributionToGenericDist(result._0), - sampEnv - ) - ); - case 4: // EvNumber - return tag("number", result._0); - case 5: // EvRecord - return tag( - "record", - _.mapValues(result._0, (x) => convertRawToTypescript(x, sampEnv)) - ); - case 6: // EvString - return tag("string", result._0); - case 7: // EvSymbol - return tag("symbol", result._0); - } -} - -function convertRawDistributionToGenericDist( - result: rescriptDist -): genericDist { - switch (result.TAG) { - case 0: // Point Set Dist - switch (result._0.TAG) { - case 0: // Mixed - return tag("PointSet", tag("Mixed", result._0._0)); - case 1: // Discrete - return tag("PointSet", tag("Discrete", result._0._0)); - case 2: // Continuous - return tag("PointSet", tag("Continuous", result._0._0)); - } - case 1: // Sample Set Dist - return tag("SampleSet", result._0); - case 2: // Symbolic Dist - return tag("Symbolic", result._0); - } -} - -// Raw rescript types. -type rescriptExport = - | { - TAG: 0; // EvArray - _0: rescriptExport[]; - } - | { - TAG: 1; // EvBool - _0: boolean; - } - | { - TAG: 2; // EvCall - _0: string; - } - | { - TAG: 3; // EvDistribution - _0: rescriptDist; - } - | { - TAG: 4; // EvNumber - _0: number; - } - | { - TAG: 5; // EvRecord - _0: { [key: string]: rescriptExport }; - } - | { - TAG: 6; // EvString - _0: string; - } - | { - TAG: 7; // EvSymbol - _0: string; - }; - -type rescriptDist = - | { TAG: 0; _0: rescriptPointSetDist } - | { TAG: 1; _0: sampleSetDist } - | { TAG: 2; _0: symbolicDist }; - -type rescriptPointSetDist = - | { - TAG: 0; // Mixed - _0: mixedShape; - } - | { - TAG: 1; // Discrete - _0: discreteShape; - } - | { - TAG: 2; // ContinuousShape - _0: continuousShape; - }; - -export function resultExn(r: result): 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; - - constructor(t: genericDist, env: samplingParams) { - this.t = t; - this.env = env; - return this; - } - - mapResultDist( - r: result - ): result { - return resultMap(r, (v: genericDist) => new Distribution(v, this.env)); - } - - mean(): result { - return Constructors_mean({ env: this.env }, this.t); - } - - sample(): result { - return Constructors_sample({ env: this.env }, this.t); - } - - pdf(n: number): result { - return Constructors_pdf({ env: this.env }, this.t, n); - } - - cdf(n: number): result { - return Constructors_cdf({ env: this.env }, this.t, n); - } - - inv(n: number): result { - return Constructors_inv({ env: this.env }, this.t, n); - } - - isNormalized(): result { - return Constructors_isNormalized({ env: this.env }, this.t); - } - - normalize(): result { - return this.mapResultDist( - Constructors_normalize({ env: this.env }, this.t) - ); - } - - type() { - return this.t.tag; - } - - pointSet(): result { - let pointSet = toPointSet( - this.t, - { - xyPointLength: this.env.xyPointLength, - sampleCount: this.env.sampleCount, - }, - undefined - ); - 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 { - return Ok({ - discrete: shapePoints(distribution.value.discrete), - continuous: shapePoints(distribution.value.continuous), - }); - } - } else { - return pointSet; - } - } - - toPointSet(): result { - return this.mapResultDist( - Constructors_toPointSet({ env: this.env }, this.t) - ); - } - - toSampleSet(n: number): result { - return this.mapResultDist( - Constructors_toSampleSet({ env: this.env }, this.t, n) - ); - } - - truncate( - left: number, - right: number - ): result { - return this.mapResultDist( - Constructors_truncate({ env: this.env }, this.t, left, right) - ); - } - - inspect(): result { - return this.mapResultDist(Constructors_inspect({ env: this.env }, this.t)); - } - - toString(): string { - let result = Constructors_toString({ env: this.env }, this.t); - if (result.tag === "Ok") { - return result.value; - } else { - return distributionErrorToString(result.value); - } - } - - toSparkline(n: number): result { - return Constructors_toSparkline({ env: this.env }, this.t, n); - } - - algebraicAdd(d2: Distribution): result { - return this.mapResultDist( - Constructors_algebraicAdd({ env: this.env }, this.t, d2.t) - ); - } - - algebraicMultiply(d2: Distribution): result { - return this.mapResultDist( - Constructors_algebraicMultiply({ env: this.env }, this.t, d2.t) - ); - } - - algebraicDivide(d2: Distribution): result { - return this.mapResultDist( - Constructors_algebraicDivide({ env: this.env }, this.t, d2.t) - ); - } - - algebraicSubtract(d2: Distribution): result { - return this.mapResultDist( - Constructors_algebraicSubtract({ env: this.env }, this.t, d2.t) - ); - } - - algebraicLogarithm( - d2: Distribution - ): result { - return this.mapResultDist( - Constructors_algebraicLogarithm({ env: this.env }, this.t, d2.t) - ); - } - - algebraicPower(d2: Distribution): result { - return this.mapResultDist( - Constructors_algebraicPower({ env: this.env }, this.t, d2.t) - ); - } - - pointwiseAdd(d2: Distribution): result { - return this.mapResultDist( - Constructors_pointwiseAdd({ env: this.env }, this.t, d2.t) - ); - } - - pointwiseMultiply(d2: Distribution): result { - return this.mapResultDist( - Constructors_pointwiseMultiply({ env: this.env }, this.t, d2.t) - ); - } - - pointwiseDivide(d2: Distribution): result { - return this.mapResultDist( - Constructors_pointwiseDivide({ env: this.env }, this.t, d2.t) - ); - } - - pointwiseSubtract(d2: Distribution): result { - return this.mapResultDist( - Constructors_pointwiseSubtract({ env: this.env }, this.t, d2.t) - ); - } - - pointwiseLogarithm( - d2: Distribution - ): result { - return this.mapResultDist( - Constructors_pointwiseLogarithm({ env: this.env }, this.t, d2.t) - ); - } - - pointwisePower(d2: Distribution): result { - return this.mapResultDist( - Constructors_pointwisePower({ env: this.env }, this.t, d2.t) - ); - } -} diff --git a/packages/squiggle-lang/src/js/rescript_interop.ts b/packages/squiggle-lang/src/js/rescript_interop.ts new file mode 100644 index 00000000..b017699f --- /dev/null +++ b/packages/squiggle-lang/src/js/rescript_interop.ts @@ -0,0 +1,155 @@ +import * as _ from "lodash"; +import { + mixedShape, + sampleSetDist, + genericDist, + samplingParams, + symbolicDist, + discreteShape, + continuousShape, +} from "../rescript/TypescriptInterface.gen"; +import { Distribution } from "./distribution"; +import { tagged, tag } from "./types"; +// This file is here to compensate for genType not fully recursively converting types + +// Raw rescript types. +export type rescriptExport = + | { + TAG: 0; // EvArray + _0: rescriptExport[]; + } + | { + TAG: 1; // EvBool + _0: boolean; + } + | { + TAG: 2; // EvCall + _0: string; + } + | { + TAG: 3; // EvDistribution + _0: rescriptDist; + } + | { + TAG: 4; // EvNumber + _0: number; + } + | { + TAG: 5; // EvRecord + _0: { [key: string]: rescriptExport }; + } + | { + TAG: 6; // EvString + _0: string; + } + | { + TAG: 7; // EvSymbol + _0: string; + }; + +type rescriptDist = + | { TAG: 0; _0: rescriptPointSetDist } + | { TAG: 1; _0: sampleSetDist } + | { TAG: 2; _0: symbolicDist }; + +type rescriptPointSetDist = + | { + TAG: 0; // Mixed + _0: mixedShape; + } + | { + TAG: 1; // Discrete + _0: discreteShape; + } + | { + TAG: 2; // ContinuousShape + _0: continuousShape; + }; + +export type squiggleExpression = + | tagged<"symbol", string> + | tagged<"string", string> + | tagged<"call", string> + | tagged<"array", squiggleExpression[]> + | tagged<"boolean", boolean> + | tagged<"distribution", Distribution> + | tagged<"number", number> + | tagged<"record", { [key: string]: squiggleExpression }>; + +export function convertRawToTypescript( + result: rescriptExport, + sampEnv: samplingParams +): squiggleExpression { + switch (result.TAG) { + case 0: // EvArray + return tag( + "array", + result._0.map((x) => convertRawToTypescript(x, sampEnv)) + ); + case 1: // EvBool + return tag("boolean", result._0); + case 2: // EvCall + return tag("call", result._0); + case 3: // EvDistribution + return tag( + "distribution", + new Distribution( + convertRawDistributionToGenericDist(result._0), + sampEnv + ) + ); + case 4: // EvNumber + return tag("number", result._0); + case 5: // EvRecord + return tag( + "record", + _.mapValues(result._0, (x) => convertRawToTypescript(x, sampEnv)) + ); + case 6: // EvString + return tag("string", result._0); + case 7: // EvSymbol + return tag("symbol", result._0); + } +} + +function convertRawDistributionToGenericDist( + result: rescriptDist +): genericDist { + switch (result.TAG) { + case 0: // Point Set Dist + switch (result._0.TAG) { + case 0: // Mixed + return tag("PointSet", tag("Mixed", result._0._0)); + case 1: // Discrete + return tag("PointSet", tag("Discrete", result._0._0)); + case 2: // Continuous + return tag("PointSet", tag("Continuous", result._0._0)); + } + case 1: // Sample Set Dist + return tag("SampleSet", result._0); + case 2: // Symbolic Dist + return tag("Symbolic", result._0); + } +} + +export type jsValue = + | string + | number + | jsValue[] + | { [key: string]: jsValue } + | boolean; + +export function jsValueToBinding(value: jsValue): rescriptExport { + if (typeof value === "boolean") { + return { TAG: 1, _0: value as boolean }; + } else if (typeof value === "string") { + return { TAG: 6, _0: value as string }; + } else if (typeof value === "number") { + return { TAG: 4, _0: value as number }; + } else if (Array.isArray(value)) { + return { TAG: 0, _0: value.map(jsValueToBinding) }; + } else { + // Record + return { TAG: 5, _0: _.mapValues(value, jsValueToBinding) }; + } +} diff --git a/packages/squiggle-lang/src/js/types.ts b/packages/squiggle-lang/src/js/types.ts new file mode 100644 index 00000000..8851b520 --- /dev/null +++ b/packages/squiggle-lang/src/js/types.ts @@ -0,0 +1,30 @@ +export type result = + | { + tag: "Ok"; + value: a; + } + | { + tag: "Error"; + value: b; + }; + +export function resultMap( + r: result, + mapFn: (x: a) => b +): result { + if (r.tag === "Ok") { + return { tag: "Ok", value: mapFn(r.value) }; + } else { + return r; + } +} + +export function Ok(x: a): result { + return { tag: "Ok", value: x }; +} + +export type tagged = { tag: a; value: b }; + +export function tag(x: a, y: b): tagged { + return { tag: x, value: y }; +} diff --git a/packages/squiggle-lang/src/rescript/Utility/E.res b/packages/squiggle-lang/src/rescript/Utility/E.res index e0bcaf5c..f5b38be7 100644 --- a/packages/squiggle-lang/src/rescript/Utility/E.res +++ b/packages/squiggle-lang/src/rescript/Utility/E.res @@ -350,7 +350,7 @@ module JsDate = { /* List */ module L = { module Util = { - let eq = (a, b) => a == b + let eq = \"==" } let fmap = List.map let get = Belt.List.get From b710289096c3ca54e8556f8e18b7bfd82479b6bb Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Fri, 29 Apr 2022 20:29:42 +0000 Subject: [PATCH 07/26] Rename parameters to imports --- .../src/components/SquiggleChart.tsx | 15 +++------ .../src/components/SquiggleEditor.tsx | 32 +++++++++++++------ .../squiggle-lang/__tests__/TS/JS_test.ts | 4 +-- .../squiggle-lang/__tests__/TS/TestHelpers.ts | 16 ++++++---- packages/squiggle-lang/src/js/index.ts | 31 +++++++++--------- 5 files changed, 53 insertions(+), 45 deletions(-) diff --git a/packages/components/src/components/SquiggleChart.tsx b/packages/components/src/components/SquiggleChart.tsx index 235a4cee..be65d425 100644 --- a/packages/components/src/components/SquiggleChart.tsx +++ b/packages/components/src/components/SquiggleChart.tsx @@ -7,8 +7,8 @@ import { squiggleExpression, bindings, samplingParams, - parameters, - defaultParameters, + jsImports, + defaultImports, defaultBindings, } from "@quri/squiggle-lang"; import { NumberShower } from "./NumberShower"; @@ -154,7 +154,7 @@ export interface SquiggleChartProps { /** Bindings of previous variables declared */ bindings?: bindings; /** JS imported parameters */ - parameters?: parameters; + imports?: jsImports; } const ChartWrapper = styled.div` @@ -170,19 +170,14 @@ export const SquiggleChart: React.FC = ({ onChange = () => {}, height = 60, bindings = defaultBindings, - parameters = defaultParameters, + imports = defaultImports, width = NaN, }: SquiggleChartProps) => { let samplingInputs: samplingParams = { sampleCount: sampleCount, xyPointLength: outputXYPoints, }; - let expressionResult = run( - squiggleString, - bindings, - samplingInputs, - parameters - ); + let expressionResult = run(squiggleString, bindings, samplingInputs, imports); let internal: JSX.Element; if (expressionResult.tag === "Ok") { let expression = expressionResult.value; diff --git a/packages/components/src/components/SquiggleEditor.tsx b/packages/components/src/components/SquiggleEditor.tsx index 67f2e73b..697e9426 100644 --- a/packages/components/src/components/SquiggleEditor.tsx +++ b/packages/components/src/components/SquiggleEditor.tsx @@ -5,13 +5,14 @@ import { CodeEditor } from "./CodeEditor"; import styled from "styled-components"; import type { squiggleExpression, + samplingParams, bindings, - parameters, + jsImports, } from "@quri/squiggle-lang"; import { runPartial, errorValueToString, - defaultParameters, + defaultImports, defaultBindings, } from "@quri/squiggle-lang"; import { ErrorBox } from "./ErrorBox"; @@ -39,8 +40,8 @@ export interface SquiggleEditorProps { width: number; /** Previous variable declarations */ bindings: bindings; - /** JS Imported parameters */ - parameters: parameters; + /** JS Imports */ + imports: jsImports; } const Input = styled.div` @@ -62,7 +63,7 @@ export let SquiggleEditor: React.FC = ({ onChange, environment, bindings = defaultBindings, - parameters = defaultParameters, + imports = defaultImports, }: SquiggleEditorProps) => { let [expression, setExpression] = React.useState(initialSquiggleString); return ( @@ -89,7 +90,7 @@ export let SquiggleEditor: React.FC = ({ environment={environment} onChange={onChange} bindings={bindings} - parameters={parameters} + imports={imports} /> ); @@ -148,18 +149,29 @@ export interface SquigglePartialProps { width: number; /** Previously declared variables */ bindings?: bindings; - /** Parameters imported from js */ - parameters?: parameters; + /** Variables imported from js */ + imports?: jsImports; } export let SquigglePartial: React.FC = ({ initialSquiggleString = "", onChange, bindings = defaultBindings, - parameters = defaultParameters, + sampleCount = 1000, + outputXYPoints = 1000, + imports = defaultImports, }: SquigglePartialProps) => { + let samplingInputs: samplingParams = { + sampleCount: sampleCount, + xyPointLength: outputXYPoints, + }; let [expression, setExpression] = React.useState(initialSquiggleString); - let squiggleResult = runPartial(expression, bindings); + let squiggleResult = runPartial( + expression, + bindings, + samplingInputs, + imports + ); if (squiggleResult.tag == "Ok") { if (onChange) onChange(squiggleResult.value); } diff --git a/packages/squiggle-lang/__tests__/TS/JS_test.ts b/packages/squiggle-lang/__tests__/TS/JS_test.ts index 004d715e..76871fc8 100644 --- a/packages/squiggle-lang/__tests__/TS/JS_test.ts +++ b/packages/squiggle-lang/__tests__/TS/JS_test.ts @@ -68,13 +68,13 @@ describe("Partials", () => { }); }); -describe("Parameters", () => { +describe("JS Imports", () => { test("Can pass parameters into partials and cells", () => { let bindings = testRunPartial(`y = $x + 2`, defaultBindings, { x: 1 }); let bindings2 = testRunPartial(`z = y + $a`, bindings, { a: 3 }); expect(testRun(`z`, bindings2)).toEqual({ tag: "number", - value: 17, + value: 6, }); }); test("Complicated deep parameters", () => { diff --git a/packages/squiggle-lang/__tests__/TS/TestHelpers.ts b/packages/squiggle-lang/__tests__/TS/TestHelpers.ts index 3bbf42d8..d9d8444f 100644 --- a/packages/squiggle-lang/__tests__/TS/TestHelpers.ts +++ b/packages/squiggle-lang/__tests__/TS/TestHelpers.ts @@ -4,12 +4,15 @@ import { bindings, squiggleExpression, errorValueToString, + defaultImports, + defaultBindings, + jsImports, } from "../../src/js/index"; export function testRun( x: string, - bindings = {}, - parameters = {} + bindings: bindings = defaultBindings, + imports: jsImports = defaultImports ): squiggleExpression { let squiggleResult = run( x, @@ -18,9 +21,8 @@ export function testRun( sampleCount: 1000, xyPointLength: 100, }, - parameters + imports ); - // return squiggleResult.value if (squiggleResult.tag === "Ok") { return squiggleResult.value; } else { @@ -34,8 +36,8 @@ export function testRun( export function testRunPartial( x: string, - bindings: bindings = {}, - parameters = {} + bindings: bindings = defaultBindings, + imports: jsImports = defaultImports ): bindings { let squiggleResult = runPartial( x, @@ -44,7 +46,7 @@ export function testRunPartial( sampleCount: 1000, xyPointLength: 100, }, - parameters + imports ); if (squiggleResult.tag === "Ok") { return squiggleResult.value; diff --git a/packages/squiggle-lang/src/js/index.ts b/packages/squiggle-lang/src/js/index.ts index 04d6050a..ce4d9428 100644 --- a/packages/squiggle-lang/src/js/index.ts +++ b/packages/squiggle-lang/src/js/index.ts @@ -16,7 +16,7 @@ export type { samplingParams, errorValue, externalBindings as bindings, - parameters, + jsImports, }; import { jsValueToBinding, @@ -28,7 +28,7 @@ import { import { result, resultMap, tag, tagged } from "./types"; import { Distribution } from "./distribution"; -export { Distribution, squiggleExpression, result }; +export { Distribution, squiggleExpression, result, resultMap }; export let defaultSamplingInputs: samplingParams = { sampleCount: 10000, @@ -39,16 +39,16 @@ export function run( squiggleString: string, bindings?: externalBindings, samplingInputs?: samplingParams, - parameters?: parameters + imports?: jsImports ): result { let b = bindings ? bindings : defaultBindings; - let p = parameters ? parameters : defaultParameters; + let i = imports ? imports : defaultImports; let si: samplingParams = samplingInputs ? samplingInputs : defaultSamplingInputs; let result: result = - evaluateUsingExternalBindings(squiggleString, mergeParameters(b, p)); + evaluateUsingExternalBindings(squiggleString, mergeImports(b, i)); return resultMap(result, (x) => createTsExport(x, si)); } @@ -57,33 +57,33 @@ export function runPartial( squiggleString: string, bindings?: externalBindings, _samplingInputs?: samplingParams, - parameters?: parameters + imports?: jsImports ): result { let b = bindings ? bindings : defaultBindings; - let p = parameters ? parameters : defaultParameters; + let i = imports ? imports : defaultImports; return evaluatePartialUsingExternalBindings( squiggleString, - mergeParameters(b, p) + mergeImports(b, i) ); } -function mergeParameters( +function mergeImports( bindings: externalBindings, - parameters: parameters + imports: jsImports ): externalBindings { - let transformedParameters = Object.fromEntries( - Object.entries(parameters).map(([key, value]) => [ + let transformedImports = Object.fromEntries( + Object.entries(imports).map(([key, value]) => [ "$" + key, jsValueToBinding(value), ]) ); - return _.merge(bindings, transformedParameters); + return _.merge(bindings, transformedImports); } -type parameters = { [key: string]: jsValue }; +type jsImports = { [key: string]: jsValue }; -export let defaultParameters: parameters = {}; +export let defaultImports: jsImports = {}; export let defaultBindings: externalBindings = {}; function createTsExport( @@ -146,4 +146,3 @@ function createTsExport( return tag("symbol", x.value); } } - From 2131e4eac165ce0fb6bf6bf1a87abe29b96b9491 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Fri, 29 Apr 2022 20:58:06 +0000 Subject: [PATCH 08/26] Rename imports to jsImports in components --- packages/components/src/components/SquiggleChart.tsx | 6 +++--- .../components/src/components/SquiggleEditor.tsx | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/components/src/components/SquiggleChart.tsx b/packages/components/src/components/SquiggleChart.tsx index be65d425..c0c5121d 100644 --- a/packages/components/src/components/SquiggleChart.tsx +++ b/packages/components/src/components/SquiggleChart.tsx @@ -154,7 +154,7 @@ export interface SquiggleChartProps { /** Bindings of previous variables declared */ bindings?: bindings; /** JS imported parameters */ - imports?: jsImports; + jsImports?: jsImports; } const ChartWrapper = styled.div` @@ -170,14 +170,14 @@ export const SquiggleChart: React.FC = ({ onChange = () => {}, height = 60, bindings = defaultBindings, - imports = defaultImports, + jsImports = defaultImports, width = NaN, }: SquiggleChartProps) => { let samplingInputs: samplingParams = { sampleCount: sampleCount, xyPointLength: outputXYPoints, }; - let expressionResult = run(squiggleString, bindings, samplingInputs, imports); + let expressionResult = run(squiggleString, bindings, samplingInputs, jsImports); let internal: JSX.Element; if (expressionResult.tag === "Ok") { let expression = expressionResult.value; diff --git a/packages/components/src/components/SquiggleEditor.tsx b/packages/components/src/components/SquiggleEditor.tsx index 697e9426..2c01f72f 100644 --- a/packages/components/src/components/SquiggleEditor.tsx +++ b/packages/components/src/components/SquiggleEditor.tsx @@ -41,7 +41,7 @@ export interface SquiggleEditorProps { /** Previous variable declarations */ bindings: bindings; /** JS Imports */ - imports: jsImports; + jsImports: jsImports; } const Input = styled.div` @@ -63,7 +63,7 @@ export let SquiggleEditor: React.FC = ({ onChange, environment, bindings = defaultBindings, - imports = defaultImports, + jsImports = defaultImports, }: SquiggleEditorProps) => { let [expression, setExpression] = React.useState(initialSquiggleString); return ( @@ -90,7 +90,7 @@ export let SquiggleEditor: React.FC = ({ environment={environment} onChange={onChange} bindings={bindings} - imports={imports} + jsImports={jsImports} /> ); @@ -150,7 +150,7 @@ export interface SquigglePartialProps { /** Previously declared variables */ bindings?: bindings; /** Variables imported from js */ - imports?: jsImports; + jsImports?: jsImports; } export let SquigglePartial: React.FC = ({ @@ -159,7 +159,7 @@ export let SquigglePartial: React.FC = ({ bindings = defaultBindings, sampleCount = 1000, outputXYPoints = 1000, - imports = defaultImports, + jsImports = defaultImports, }: SquigglePartialProps) => { let samplingInputs: samplingParams = { sampleCount: sampleCount, @@ -170,7 +170,7 @@ export let SquigglePartial: React.FC = ({ expression, bindings, samplingInputs, - imports + jsImports ); if (squiggleResult.tag == "Ok") { if (onChange) onChange(squiggleResult.value); From d09dbeb812f6609e9c4605bdabbd120ea4c70581 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Fri, 29 Apr 2022 20:59:37 +0000 Subject: [PATCH 09/26] Format components code --- packages/components/src/components/SquiggleChart.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/components/src/components/SquiggleChart.tsx b/packages/components/src/components/SquiggleChart.tsx index c0c5121d..31cd9787 100644 --- a/packages/components/src/components/SquiggleChart.tsx +++ b/packages/components/src/components/SquiggleChart.tsx @@ -177,7 +177,12 @@ export const SquiggleChart: React.FC = ({ sampleCount: sampleCount, xyPointLength: outputXYPoints, }; - let expressionResult = run(squiggleString, bindings, samplingInputs, jsImports); + let expressionResult = run( + squiggleString, + bindings, + samplingInputs, + jsImports + ); let internal: JSX.Element; if (expressionResult.tag === "Ok") { let expression = expressionResult.value; From 3117dd81d60955d72eed7aa75ad5a4aa6116d6d2 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Fri, 29 Apr 2022 21:16:22 +0000 Subject: [PATCH 10/26] Remove si prefix from chart axis --- packages/components/src/vega-specs/spec-distributions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/vega-specs/spec-distributions.json b/packages/components/src/vega-specs/spec-distributions.json index 129183a5..5b6ed261 100644 --- a/packages/components/src/vega-specs/spec-distributions.json +++ b/packages/components/src/vega-specs/spec-distributions.json @@ -88,7 +88,7 @@ "tickOpacity": 0.0, "domainColor": "#fff", "domainOpacity": 0.0, - "format": "~s", + "format": "~g", "tickCount": 10 } ], From 8217801de33c74b5c7e83eebe635c779c8f118b3 Mon Sep 17 00:00:00 2001 From: Quinn Dougherty Date: Fri, 29 Apr 2022 18:38:55 -0400 Subject: [PATCH 11/26] magic numbers in bandwidth; `fromSamples` implementation Value: [1e-3 to 4e-2] --- .../__tests__/TS/SampleSet_test.ts | 16 +++++++++++++++- packages/squiggle-lang/src/js/index.ts | 5 +++++ .../DistributionOperation.res | 7 +++++++ .../DistributionOperation.resi | 2 ++ .../Distributions/DistributionTypes.res | 13 +++++++------ .../SampleSetDist/SampleSetDist.res | 3 ++- .../SampleSetDist/SampleSetDist_Bandwidth.res | 19 +++++++++++-------- .../src/rescript/MagicNumbers.res | 13 +++++++++++++ .../ReducerInterface_GenericDistribution.res | 11 +++++++++++ .../squiggle-lang/src/rescript/Utility/E.res | 2 ++ 10 files changed, 75 insertions(+), 16 deletions(-) diff --git a/packages/squiggle-lang/__tests__/TS/SampleSet_test.ts b/packages/squiggle-lang/__tests__/TS/SampleSet_test.ts index a617010b..356f19a4 100644 --- a/packages/squiggle-lang/__tests__/TS/SampleSet_test.ts +++ b/packages/squiggle-lang/__tests__/TS/SampleSet_test.ts @@ -1,5 +1,5 @@ import { Distribution } from "../../src/js/index"; -import { expectErrorToBeBounded, failDefault } from "./TestHelpers"; +import { expectErrorToBeBounded, failDefault, testRun } from "./TestHelpers"; import * as fc from "fast-check"; // Beware: float64Array makes it appear in an infinite loop. @@ -212,3 +212,17 @@ describe("mean is mean", () => { ); }); }); + +describe("fromSamples function", () => { + test("gives a mean near the mean of the input", () => { + fc.assert( + fc.property(arrayGen(), (xs_) => { + let xs = Array.from(xs_); + let squiggleString = `x = fromSamples($xs); mean(x)`; + let squiggleResult = testRun(squiggleString, {}, { xs: xs }); + let mean = xs.reduce((a, b) => a + b, 0.0) / xs.length; + expect(squiggleResult.value).toBeCloseTo(mean, 3); + }) + ); + }); +}); diff --git a/packages/squiggle-lang/src/js/index.ts b/packages/squiggle-lang/src/js/index.ts index fb67e47a..d72eb5c7 100644 --- a/packages/squiggle-lang/src/js/index.ts +++ b/packages/squiggle-lang/src/js/index.ts @@ -31,6 +31,7 @@ import { Constructors_isNormalized, Constructors_toPointSet, Constructors_toSampleSet, + Constructors_fromSamples, Constructors_truncate, Constructors_inspect, Constructors_toString, @@ -404,6 +405,10 @@ export class Distribution { ); } + fromSamples(n: Array): result { + return this.mapResultDist(Constructors_fromSamples({ env: this.env }, n)); + } + truncate( left: number, right: number diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res index 18ee2d6a..22376589 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res @@ -189,6 +189,12 @@ let rec run = (~env, functionCallInfo: functionCallInfo): outputType => { ->GenericDist.mixture(~scaleMultiplyFn=scaleMultiply, ~pointwiseAddFn=pointwiseAdd) ->E.R2.fmap(r => Dist(r)) ->OutputLocal.fromResult + | FromArray(xs) => + xs + ->SampleSetDist.make + ->E.R2.fmap2(x => DistributionTypes.SampleSetError(x)) + ->E.R2.fmap(x => x->DistributionTypes.SampleSet->Dist) + ->OutputLocal.fromResult } } @@ -229,6 +235,7 @@ module Constructors = { let isNormalized = (~env, dist) => C.isNormalized(dist)->run(~env)->toBoolR let toPointSet = (~env, dist) => C.toPointSet(dist)->run(~env)->toDistR let toSampleSet = (~env, dist, n) => C.toSampleSet(dist, n)->run(~env)->toDistR + let fromSamples = (~env, xs) => C.fromSamples(xs)->run(~env)->toDistR let truncate = (~env, dist, leftCutoff, rightCutoff) => C.truncate(dist, leftCutoff, rightCutoff)->run(~env)->toDistR let inspect = (~env, dist) => C.inspect(dist)->run(~env)->toDistR diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.resi b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.resi index 5ad34354..fcaeb5e4 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.resi +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.resi @@ -61,6 +61,8 @@ module Constructors: { @genType let toSampleSet: (~env: env, genericDist, int) => result @genType + let fromSamples: (~env: env, SampleSetDist.t) => result + @genType let truncate: (~env: env, genericDist, option, option) => result @genType let inspect: (~env: env, genericDist) => result diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res b/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res index 93f86798..a1725c88 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res @@ -11,7 +11,7 @@ type error = | NotYetImplemented | Unreachable | DistributionVerticalShiftIsInvalid - | TooFewSamples + | SampleSetError(SampleSetDist.sampleSetError) | ArgumentError(string) | OperationError(Operation.Error.t) | PointSetConversionError(SampleSetDist.pointsetConversionError) @@ -35,7 +35,8 @@ module Error = { | DistributionVerticalShiftIsInvalid => "Distribution Vertical Shift is Invalid" | ArgumentError(s) => `Argument Error ${s}` | LogarithmOfDistributionError(s) => `Logarithm of input error: ${s}` - | TooFewSamples => "Too Few Samples" + | SampleSetError(TooFewSamples) => "Too Few Samples" + | SampleSetError(NonNumericInput(err)) => `Found a non-number in input: ${err}` | OperationError(err) => Operation.Error.toString(err) | PointSetConversionError(err) => SampleSetDist.pointsetConversionErrorToString(err) | SparklineError(err) => PointSetTypes.sparklineErrorToString(err) @@ -47,10 +48,7 @@ module Error = { let resultStringToResultError: result<'a, string> => result<'a, error> = n => n->E.R2.errMap(r => r->fromString) - let sampleErrorToDistErr = (err: SampleSetDist.sampleSetError): error => - switch err { - | TooFewSamples => TooFewSamples - } + let sampleErrorToDistErr = (err: SampleSetDist.sampleSetError): error => SampleSetError(err) } @genType @@ -100,6 +98,7 @@ module DistributionOperation = { | FromDist(fromDist, genericDist) | FromFloat(fromDist, float) | Mixture(array<(genericDist, float)>) + | FromArray(SampleSetDist.t) let distCallToString = (distFunction: fromDist): string => switch distFunction { @@ -124,6 +123,7 @@ module DistributionOperation = { switch d { | FromDist(f, _) | FromFloat(f, _) => distCallToString(f) | Mixture(_) => `mixture` + | FromArray(_) => `samples` } } module Constructors = { @@ -140,6 +140,7 @@ module Constructors = { let isNormalized = (dist): t => FromDist(ToBool(IsNormalized), dist) let toPointSet = (dist): t => FromDist(ToDist(ToPointSet), dist) let toSampleSet = (dist, r): t => FromDist(ToDist(ToSampleSet(r)), dist) + let fromSamples = (xs): t => FromArray(xs) let truncate = (dist, left, right): t => FromDist(ToDist(Truncate(left, right)), dist) let inspect = (dist): t => FromDist(ToDist(Inspect), dist) let toString = (dist): t => FromDist(ToString(ToString), dist) diff --git a/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSetDist.res b/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSetDist.res index 14c66812..55b334c5 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSetDist.res +++ b/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSetDist.res @@ -1,11 +1,12 @@ @genType module Error = { @genType - type sampleSetError = TooFewSamples + type sampleSetError = TooFewSamples | NonNumericInput(string) let sampleSetErrorToString = (err: sampleSetError): string => switch err { | TooFewSamples => "Too few samples when constructing sample set" + | NonNumericInput(err) => `Found a non-number in input: ${err}` } @genType diff --git a/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSetDist_Bandwidth.res b/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSetDist_Bandwidth.res index aef659d1..29d48ad3 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSetDist_Bandwidth.res +++ b/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSetDist_Bandwidth.res @@ -1,27 +1,30 @@ //The math here was taken from https://github.com/jasondavies/science.js/blob/master/src/stats/SampleSetDist_Bandwidth.js - +let {iqr_percentile, nrd0_lo_denominator, one, nrd0_coef, nrd_coef, nrd_fractionalPower} = module( + MagicNumbers.SampleSetBandwidth +) let len = x => E.A.length(x) |> float_of_int -let iqr = x => Jstat.percentile(x, 0.75, true) -. Jstat.percentile(x, 0.25, true) +let iqr = x => + Jstat.percentile(x, iqr_percentile, true) -. Jstat.percentile(x, 1.0 -. iqr_percentile, true) // Silverman, B. W. (1986) Density Estimation. London: Chapman and Hall. let nrd0 = x => { let hi = Js_math.sqrt(Jstat.variance(x)) - let lo = Js_math.minMany_float([hi, iqr(x) /. 1.34]) + let lo = Js_math.minMany_float([hi, iqr(x) /. nrd0_lo_denominator]) let e = Js_math.abs_float(x[1]) let lo' = switch (lo, hi, e) { | (lo, _, _) if !Js.Float.isNaN(lo) => lo | (_, hi, _) if !Js.Float.isNaN(hi) => hi | (_, _, e) if !Js.Float.isNaN(e) => e - | _ => 1.0 + | _ => one } - 0.9 *. lo' *. Js.Math.pow_float(~base=len(x), ~exp=-0.2) + nrd0_coef *. lo' *. Js.Math.pow_float(~base=len(x), ~exp=nrd_fractionalPower) } // Scott, D. W. (1992) Multivariate Density Estimation: Theory, Practice, and Visualization. Wiley. let nrd = x => { - let h = iqr(x) /. 1.34 - 1.06 *. + let h = iqr(x) /. nrd0_lo_denominator + nrd_coef *. Js.Math.min_float(Js.Math.sqrt(Jstat.variance(x)), h) *. - Js.Math.pow_float(~base=len(x), ~exp=-1.0 /. 5.0) + Js.Math.pow_float(~base=len(x), ~exp=nrd_fractionalPower) } diff --git a/packages/squiggle-lang/src/rescript/MagicNumbers.res b/packages/squiggle-lang/src/rescript/MagicNumbers.res index 124a44f4..0f059c03 100644 --- a/packages/squiggle-lang/src/rescript/MagicNumbers.res +++ b/packages/squiggle-lang/src/rescript/MagicNumbers.res @@ -35,3 +35,16 @@ module ToPointSet = { */ let minDiscreteToKeep = samples => max(20, E.A.length(samples) / 50) } + +module SampleSetBandwidth = { + // Silverman, B. W. (1986) Density Estimation. London: Chapman and Hall. + // Scott, D. W. (1992) Multivariate Density Estimation: Theory, Practice, and Visualization. Wiley. + let iqr_percentile = 0.75 + let iqr_percentile_complement = 1.0 -. iqr_percentile + let nrd0_lo_denominator = 1.34 + let one = 1.0 + let nrd0_coef = 0.9 + + let nrd_coef = 1.06 + let nrd_fractionalPower = -0.2 +} diff --git a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res index ab76f469..49165f0f 100644 --- a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res @@ -218,6 +218,17 @@ let dispatchToGenericOutput = (call: ExpressionValue.functionCall): option< Helpers.toDistFn(ToSampleSet(Belt.Int.fromFloat(float)), dist) | ("toSampleSet", [EvDistribution(dist)]) => Helpers.toDistFn(ToSampleSet(MagicNumbers.Environment.defaultSampleCount), dist) + | ("fromSamples", [EvArray(arr)]) => + Helpers.toDistFn( + ToSampleSet(MagicNumbers.Environment.defaultSampleCount), + arr + ->Helpers.parseNumberArray + ->E.R2.fmap2(x => SampleSetDist.NonNumericInput(x)) + ->E.R.bind(SampleSetDist.make) + ->E.R2.fmap(x => DistributionTypes.SampleSet(x)) + // Raising here isn't ideal. This: GenDistError(SampleSetError(NonNumericInput("Something wasn't a number"))) would be proper. + ->E.R2.toExn("Something in the input wasn't a number"), + ) | ("inspect", [EvDistribution(dist)]) => Helpers.toDistFn(Inspect, dist) | ("truncateLeft", [EvDistribution(dist), EvNumber(float)]) => Helpers.toDistFn(Truncate(Some(float), None), dist) diff --git a/packages/squiggle-lang/src/rescript/Utility/E.res b/packages/squiggle-lang/src/rescript/Utility/E.res index e0bcaf5c..5b3280d8 100644 --- a/packages/squiggle-lang/src/rescript/Utility/E.res +++ b/packages/squiggle-lang/src/rescript/Utility/E.res @@ -307,6 +307,8 @@ module R2 = { | Ok(x) => x->Ok | Error(x) => x->f->Error } + + let toExn = (a, b) => R.toExn(b, a) } let safe_fn_of_string = (fn, s: string): option<'a> => From ba0baf31c67cc0664d1df3ce55ace32afd73d63d Mon Sep 17 00:00:00 2001 From: Quinn Dougherty Date: Fri, 29 Apr 2022 18:45:12 -0400 Subject: [PATCH 12/26] Fixed a (now skipped) test [1e-5 to 1e-4] --- packages/squiggle-lang/__tests__/TS/SampleSet_test.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/squiggle-lang/__tests__/TS/SampleSet_test.ts b/packages/squiggle-lang/__tests__/TS/SampleSet_test.ts index 356f19a4..2c77e210 100644 --- a/packages/squiggle-lang/__tests__/TS/SampleSet_test.ts +++ b/packages/squiggle-lang/__tests__/TS/SampleSet_test.ts @@ -214,14 +214,15 @@ describe("mean is mean", () => { }); describe("fromSamples function", () => { - test("gives a mean near the mean of the input", () => { + test.skip("gives a mean near the mean of the input", () => { fc.assert( fc.property(arrayGen(), (xs_) => { let xs = Array.from(xs_); - let squiggleString = `x = fromSamples($xs); mean(x)`; - let squiggleResult = testRun(squiggleString, {}, { xs: xs }); + let xsString = xs.toString(); + let squiggleString = `x = fromSamples([${xsString}]); mean(x)`; + let squiggleResult = testRun(squiggleString); let mean = xs.reduce((a, b) => a + b, 0.0) / xs.length; - expect(squiggleResult.value).toBeCloseTo(mean, 3); + expect(squiggleResult.value).toBeCloseTo(mean, 4); }) ); }); From 3249f6915522ff963b842a38cb008d1dc284b837 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Fri, 29 Apr 2022 21:41:09 -0400 Subject: [PATCH 13/26] Small cleanup to fromSamples --- .../DistributionOperation.res | 5 ++--- .../Distributions/DistributionTypes.res | 6 +++--- .../ReducerInterface_GenericDistribution.res | 19 ++++++++----------- .../squiggle-lang/src/rescript/Utility/E.res | 7 +++++++ 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res index 22376589..f323cdcb 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res @@ -189,10 +189,9 @@ let rec run = (~env, functionCallInfo: functionCallInfo): outputType => { ->GenericDist.mixture(~scaleMultiplyFn=scaleMultiply, ~pointwiseAddFn=pointwiseAdd) ->E.R2.fmap(r => Dist(r)) ->OutputLocal.fromResult - | FromArray(xs) => - xs + | FromSamples(xs) => xs ->SampleSetDist.make - ->E.R2.fmap2(x => DistributionTypes.SampleSetError(x)) + ->E.R2.errMap(x => DistributionTypes.SampleSetError(x)) ->E.R2.fmap(x => x->DistributionTypes.SampleSet->Dist) ->OutputLocal.fromResult } diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res b/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res index a1725c88..c5b9a4ef 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res @@ -97,8 +97,8 @@ module DistributionOperation = { type genericFunctionCallInfo = | FromDist(fromDist, genericDist) | FromFloat(fromDist, float) + | FromSamples(array) | Mixture(array<(genericDist, float)>) - | FromArray(SampleSetDist.t) let distCallToString = (distFunction: fromDist): string => switch distFunction { @@ -123,7 +123,7 @@ module DistributionOperation = { switch d { | FromDist(f, _) | FromFloat(f, _) => distCallToString(f) | Mixture(_) => `mixture` - | FromArray(_) => `samples` + | FromSamples(_) => `fromSamples` } } module Constructors = { @@ -140,7 +140,7 @@ module Constructors = { let isNormalized = (dist): t => FromDist(ToBool(IsNormalized), dist) let toPointSet = (dist): t => FromDist(ToDist(ToPointSet), dist) let toSampleSet = (dist, r): t => FromDist(ToDist(ToSampleSet(r)), dist) - let fromSamples = (xs): t => FromArray(xs) + let fromSamples = (xs): t => FromSamples(xs) let truncate = (dist, left, right): t => FromDist(ToDist(Truncate(left, right)), dist) let inspect = (dist): t => FromDist(ToDist(Inspect), dist) let toString = (dist): t => FromDist(ToString(ToString), dist) diff --git a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res index 49165f0f..5277ae1c 100644 --- a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res @@ -218,17 +218,14 @@ let dispatchToGenericOutput = (call: ExpressionValue.functionCall): option< Helpers.toDistFn(ToSampleSet(Belt.Int.fromFloat(float)), dist) | ("toSampleSet", [EvDistribution(dist)]) => Helpers.toDistFn(ToSampleSet(MagicNumbers.Environment.defaultSampleCount), dist) - | ("fromSamples", [EvArray(arr)]) => - Helpers.toDistFn( - ToSampleSet(MagicNumbers.Environment.defaultSampleCount), - arr - ->Helpers.parseNumberArray - ->E.R2.fmap2(x => SampleSetDist.NonNumericInput(x)) - ->E.R.bind(SampleSetDist.make) - ->E.R2.fmap(x => DistributionTypes.SampleSet(x)) - // Raising here isn't ideal. This: GenDistError(SampleSetError(NonNumericInput("Something wasn't a number"))) would be proper. - ->E.R2.toExn("Something in the input wasn't a number"), - ) + | ("fromSamples", [EvArray(inputArray)]) => { + let _wrapInputErrors = x => SampleSetDist.NonNumericInput(x) + let parsedArray = Helpers.parseNumberArray(inputArray)->E.R2.errMap(_wrapInputErrors) + switch parsedArray { + | Ok(array) => runGenericOperation(FromSamples(array)) + | Error(e) => GenDistError(SampleSetError(e)) + }->Some + } | ("inspect", [EvDistribution(dist)]) => Helpers.toDistFn(Inspect, dist) | ("truncateLeft", [EvDistribution(dist), EvNumber(float)]) => Helpers.toDistFn(Truncate(Some(float), None), dist) diff --git a/packages/squiggle-lang/src/rescript/Utility/E.res b/packages/squiggle-lang/src/rescript/Utility/E.res index 5b3280d8..9edeae1b 100644 --- a/packages/squiggle-lang/src/rescript/Utility/E.res +++ b/packages/squiggle-lang/src/rescript/Utility/E.res @@ -289,6 +289,13 @@ module R = { | Ok(r) => r->Ok | Error(x) => x->f->Error } + + //I'm not sure what to call this. + let unify = (a: result<'a, 'b>, c: 'b => 'a): 'a => + switch a { + | Ok(x) => x + | Error(x) => c(x) + } } module R2 = { From e724f43b9d9bafc7cf8220b6a6f9f41b77040a00 Mon Sep 17 00:00:00 2001 From: Quinn Dougherty Date: Sat, 30 Apr 2022 10:01:55 -0400 Subject: [PATCH 14/26] Documented `fromSamples` Value: [1e-4 to 1e-3] --- packages/website/docs/Features/Functions.mdx | 32 ++++++++++++-------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/packages/website/docs/Features/Functions.mdx b/packages/website/docs/Features/Functions.mdx index e37ea315..8282b11c 100644 --- a/packages/website/docs/Features/Functions.mdx +++ b/packages/website/docs/Features/Functions.mdx @@ -315,6 +315,26 @@ Or `PointSet` format +### `toSampleSet` has two signatures + +Above, we saw the unary `toSampleSet`, which uses an internal hardcoded number of samples. If you'd like to provide the number of samples, it has a binary signature as well (floored) + + + +#### Validity + +- Second argument to `toSampleSet` must be a number. + +## `fromSamples` + + +#### Validity + +For `fromSamples(xs)`, + +- `xs.length > 5` +- Strictly every element of `xs` must be a number. + ## Normalization Some distribution operations (like horizontal shift) return an unnormalized distriibution. @@ -333,18 +353,6 @@ We provide a predicate `isNormalized`, for when we have simple control flow - Input to `isNormalized` must be a dist -## Convert any distribution to a sample set distribution - -`toSampleSet` has two signatures - -It is unary when you use an internal hardcoded number of samples - - - -And binary when you provide a number of samples (floored) - - - ## `inspect` You may like to debug by right clicking your browser and using the _inspect_ functionality on the webpage, and viewing the _console_ tab. Then, wrap your squiggle output with `inspect` to log an internal representation. From f3561317fdd12c5104715739b93fb08f85364fc1 Mon Sep 17 00:00:00 2001 From: Quinn Dougherty Date: Sat, 30 Apr 2022 10:10:09 -0400 Subject: [PATCH 15/26] Moved `fromSamples` to `Inventory` section Value: [1e-7 to 1e-5] --- packages/website/docs/Features/Functions.mdx | 23 +++++++++++--------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/website/docs/Features/Functions.mdx b/packages/website/docs/Features/Functions.mdx index 8282b11c..1de7514b 100644 --- a/packages/website/docs/Features/Functions.mdx +++ b/packages/website/docs/Features/Functions.mdx @@ -98,6 +98,19 @@ bound `a`, mode `b` and upper bound `c`. Squiggle, when the context is right, automatically casts a float to a constant distribution. +## `fromSamples` + +The last distribution constructor takes an array of samples and constructs a sample set distribution. + + + +#### Validity + +For `fromSamples(xs)`, + +- `xs.length > 5` +- Strictly every element of `xs` must be a number. + ## Operating on distributions Here are the ways we combine distributions. @@ -325,16 +338,6 @@ Above, we saw the unary `toSampleSet`, which uses an internal hardcoded number o - Second argument to `toSampleSet` must be a number. -## `fromSamples` - - -#### Validity - -For `fromSamples(xs)`, - -- `xs.length > 5` -- Strictly every element of `xs` must be a number. - ## Normalization Some distribution operations (like horizontal shift) return an unnormalized distriibution. From 9fe7034c518b6d6ecc42aa2cb21bdd9185acbc0c Mon Sep 17 00:00:00 2001 From: Quinn Dougherty Date: Sat, 30 Apr 2022 11:33:03 -0400 Subject: [PATCH 16/26] v0.2.8: `fromSamples` and jsImports --- packages/squiggle-lang/README.md | 15 +++++++++++++++ packages/squiggle-lang/package.json | 6 ++++-- .../DistributionOperation.res | 3 ++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/packages/squiggle-lang/README.md b/packages/squiggle-lang/README.md index 05bb969c..4513ee76 100644 --- a/packages/squiggle-lang/README.md +++ b/packages/squiggle-lang/README.md @@ -3,6 +3,21 @@ # Squiggle language +## Use the `npm` package + +For instance, in a fresh `create-react-app`, you can + +```sh +yarn add @quri/squiggle-lang +``` + +```js +import {run} from '@quri/squiggle-lang'; +run("normal(0, 1) * fromSamples([-3,-2,-1,1,2,3,3,3,4,9]").value.value.toSparkline().value) +``` + +**However, for most use cases you'll prefer to use our [library of react components](https://www.npmjs.com/package/@quri/squiggle-components)**, and let your app transitively depend on `@quri/squiggle-lang`. + ## Build for development We assume that you ran `yarn` at the monorepo level. diff --git a/packages/squiggle-lang/package.json b/packages/squiggle-lang/package.json index 4d146ef8..34930989 100644 --- a/packages/squiggle-lang/package.json +++ b/packages/squiggle-lang/package.json @@ -1,6 +1,6 @@ { "name": "@quri/squiggle-lang", - "version": "0.2.7", + "version": "0.2.8", "homepage": "https://squiggle-language.com", "license": "MIT", "scripts": { @@ -24,6 +24,7 @@ "format:rescript": "rescript format -all", "format:prettier": "prettier --write .", "format": "yarn format:rescript && yarn format:prettier", + "prepack": "yarn build && yarn test && yarn bundle", "all": "yarn build && yarn bundle && yarn test" }, "keywords": [ @@ -35,7 +36,7 @@ "rescript": "^9.1.4", "jstat": "^1.9.5", "pdfast": "^0.2.0", - "mathjs": "10.5.0" + "mathjs": "^10.5.0" }, "devDependencies": { "bisect_ppx": "^2.7.1", @@ -61,6 +62,7 @@ "webpack-cli": "^4.9.2" }, "source": "./src/js/index.ts", + "browser": "./dist/bundle.js", "main": "./dist/src/js/index.js", "types": "./dist/src/js/index.d.ts" } diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res index f323cdcb..db6656b2 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res @@ -189,7 +189,8 @@ let rec run = (~env, functionCallInfo: functionCallInfo): outputType => { ->GenericDist.mixture(~scaleMultiplyFn=scaleMultiply, ~pointwiseAddFn=pointwiseAdd) ->E.R2.fmap(r => Dist(r)) ->OutputLocal.fromResult - | FromSamples(xs) => xs + | FromSamples(xs) => + xs ->SampleSetDist.make ->E.R2.errMap(x => DistributionTypes.SampleSetError(x)) ->E.R2.fmap(x => x->DistributionTypes.SampleSet->Dist) From 93ef7c76a01ac39e6afbfc4d8f1b6b56485c21c7 Mon Sep 17 00:00:00 2001 From: Quinn Dougherty Date: Sat, 30 Apr 2022 12:04:03 -0400 Subject: [PATCH 17/26] v0.2.16: jsImports prop and incremented minimal squiggle-lang Value: [1e-5 to 1e-3] --- packages/components/README.md | 12 +++--------- packages/components/package.json | 14 +++++++------- packages/squiggle-lang/README.md | 16 ++++++++++------ 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/packages/components/README.md b/packages/components/README.md index ad35c67f..4d073a14 100644 --- a/packages/components/README.md +++ b/packages/components/README.md @@ -1,9 +1,9 @@ [![npm version](https://badge.fury.io/js/@quri%2Fsquiggle-components.svg)](https://www.npmjs.com/package/@quri/squiggle-components) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/quantified-uncertainty/squiggle/blob/develop/LICENSE) -# Squiggle Components +# Squiggle components -This package contains all the components for squiggle. These can be used either as a library or hosted as a [storybook](https://storybook.js.org/). +This package contains the react components for squiggle. These can be used either as a library or hosted as a [storybook](https://storybook.js.org/). # Usage in a `react` project @@ -17,7 +17,7 @@ Add to `App.js`: ```jsx import { SquiggleEditor } from "@quri/squiggle-components"; -; +; ``` # Build storybook for development @@ -38,9 +38,3 @@ Run a development server ```sh yarn start ``` - -And build artefacts for production, - -```sh -yarn build # builds storybook app -``` diff --git a/packages/components/package.json b/packages/components/package.json index 3b50afbf..fbdd476a 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,9 +1,9 @@ { "name": "@quri/squiggle-components", - "version": "0.2.15", + "version": "0.2.16", "license": "MIT", "dependencies": { - "@quri/squiggle-lang": "^0.2.7", + "@quri/squiggle-lang": "^0.2.8", "@react-hook/size": "^2.1.2", "lodash": "^4.17.21", "react": "^18.1.0", @@ -49,11 +49,11 @@ "scripts": { "start": "cross-env REACT_APP_FAST_REFRESH=false && start-storybook -p 6006 -s public", "build": "tsc -b && build-storybook -s public", - "build:package": "tsc -b", "bundle": "webpack", "all": "yarn bundle && yarn build", "lint": "prettier --check .", - "format": "prettier --write ." + "format": "prettier --write .", + "prepack": "yarn bundle && tsc -b" }, "eslintConfig": { "extends": [ @@ -87,7 +87,7 @@ "@types/react": "17.0.43" }, "source": "./src/index.ts", - "browser": "dist/bundle.js", - "main": "dist/src/index.js", - "types": "dist/src/index.d.ts" + "browser": "./dist/bundle.js", + "main": "./dist/src/index.js", + "types": "./dist/src/index.d.ts" } diff --git a/packages/squiggle-lang/README.md b/packages/squiggle-lang/README.md index 4513ee76..f6735454 100644 --- a/packages/squiggle-lang/README.md +++ b/packages/squiggle-lang/README.md @@ -3,22 +3,26 @@ # Squiggle language -## Use the `npm` package +_An estimation language_ -For instance, in a fresh `create-react-app`, you can +# Use the `npm` package + +For instance, in a javascript project, you can ```sh yarn add @quri/squiggle-lang ``` ```js -import {run} from '@quri/squiggle-lang'; -run("normal(0, 1) * fromSamples([-3,-2,-1,1,2,3,3,3,4,9]").value.value.toSparkline().value) +import { run } from "@quri/squiggle-lang"; +run( + "normal(0, 1) * fromSamples([-3,-2,-1,1,2,3,3,3,4,9]" +).value.value.toSparkline().value; ``` **However, for most use cases you'll prefer to use our [library of react components](https://www.npmjs.com/package/@quri/squiggle-components)**, and let your app transitively depend on `@quri/squiggle-lang`. -## Build for development +# Build for development We assume that you ran `yarn` at the monorepo level. @@ -38,7 +42,7 @@ yarn test yarn coverage:rescript; o _coverage/index.html # produces coverage report and opens it in browser ``` -## Distributing this package or using this package from other monorepo packages +# Distributing this package or using this package from other monorepo packages As it says in the other `packages/*/README.md`s, building this package is an essential step of building other packages. From 1aea9b6c0830ea69899cd7a78c0e98d5d939e477 Mon Sep 17 00:00:00 2001 From: Quinn Dougherty Date: Sat, 30 Apr 2022 12:16:47 -0400 Subject: [PATCH 18/26] fixed dead material in `yarn.lock` Value: [1e-9 to 1e-6] --- yarn.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index 3597fea6..ec55f879 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11751,7 +11751,7 @@ markdown-to-jsx@^7.1.3: resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-7.1.7.tgz#a5f22102fb12241c8cea1ca6a4050bb76b23a25d" integrity sha512-VI3TyyHlGkO8uFle0IOibzpO1c1iJDcXcS/zBrQrXQQvJ2tpdwVzVZ7XdKsyRz1NdRmre4dqQkMZzUHaKIG/1w== -mathjs@10.5.0: +mathjs@^10.5.0: version "10.5.0" resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-10.5.0.tgz#f81d0518fe7b4b2a0b85e1125b8ecfc364fb0292" integrity sha512-gRnSY9psN9zgiB2QV9F4XbuX5hwjxY5Ou7qoTFWDbn2vZ3UEs+sjfK/SRg2WP30TNfZWpwlGdp8H1knFJnpFdA== From a3057789b0957516d84a91e666a516e8dc29d92b Mon Sep 17 00:00:00 2001 From: Quinn Dougherty Date: Sat, 30 Apr 2022 12:52:13 -0400 Subject: [PATCH 19/26] `^`-version everything Value: [1e-9 to 1e-6] --- packages/components/package.json | 4 ++-- packages/squiggle-lang/package.json | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/components/package.json b/packages/components/package.json index fbdd476a..fbddaf2c 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -7,7 +7,7 @@ "@react-hook/size": "^2.1.2", "lodash": "^4.17.21", "react": "^18.1.0", - "react-ace": "10.1.0", + "react-ace": "^10.1.0", "react-dom": "^18.1.0", "react-vega": "^7.5.0", "styled-components": "^5.3.5", @@ -36,7 +36,7 @@ "@types/styled-components": "^5.1.24", "@types/webpack": "^5.28.0", "cross-env": "^7.0.3", - "react-scripts": "5.0.1", + "react-scripts": "^5.0.1", "style-loader": "^3.3.1", "ts-loader": "^9.2.9", "tsconfig-paths-webpack-plugin": "^3.5.2", diff --git a/packages/squiggle-lang/package.json b/packages/squiggle-lang/package.json index 34930989..ab3e0b72 100644 --- a/packages/squiggle-lang/package.json +++ b/packages/squiggle-lang/package.json @@ -40,18 +40,18 @@ }, "devDependencies": { "bisect_ppx": "^2.7.1", - "lodash": "4.17.21", + "lodash": "^4.17.21", "rescript-fast-check": "^1.1.1", "@glennsl/rescript-jest": "^0.9.0", "@istanbuljs/nyc-config-typescript": "^1.0.2", "@types/jest": "^27.4.0", "babel-plugin-transform-es2015-modules-commonjs": "^6.26.2", "chalk": "^5.0.1", - "codecov": "3.8.3", - "fast-check": "2.25.0", + "codecov": "^3.8.3", + "fast-check": "^2.25.0", "gentype": "^4.3.0", "jest": "^27.5.1", - "moduleserve": "0.9.1", + "moduleserve": "^0.9.1", "nyc": "^15.1.0", "reanalyze": "^2.19.0", "ts-jest": "^27.1.4", From 05ec19b2a43a0f9d96e24a800000271c26d6f9df Mon Sep 17 00:00:00 2001 From: Quinn Dougherty Date: Sat, 30 Apr 2022 12:56:45 -0400 Subject: [PATCH 20/26] `^`-version everything: `yarn.lock` update Value: [1e-10 to 1e-6] --- yarn.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/yarn.lock b/yarn.lock index ec55f879..89928253 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6498,7 +6498,7 @@ coa@^2.0.2: chalk "^2.4.1" q "^1.1.2" -codecov@3.8.3: +codecov@^3.8.3: version "3.8.3" resolved "https://registry.yarnpkg.com/codecov/-/codecov-3.8.3.tgz#9c3e364b8a700c597346ae98418d09880a3fdbe7" integrity sha512-Y8Hw+V3HgR7V71xWH2vQ9lyS358CbGCldWlJFR0JirqoGtOoas3R3/OclRTvgUYFK29mmJICDPauVKmpqbwhOA== @@ -8607,7 +8607,7 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" -fast-check@2.25.0, fast-check@^2.17.0: +fast-check@^2.17.0, fast-check@^2.25.0: version "2.25.0" resolved "https://registry.yarnpkg.com/fast-check/-/fast-check-2.25.0.tgz#5146601851bf3be0953bd17eb2b7d547936c6561" integrity sha512-wRUT2KD2lAmT75WNIJIHECawoUUMHM0I5jrlLXGtGeqmPL8jl/EldUDjY1VCp6fDY8yflyfUeIOsOBrIbIiArg== @@ -11627,7 +11627,7 @@ lodash.uniq@4.5.0, lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0: +lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -12120,7 +12120,7 @@ mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -moduleserve@0.9.1: +moduleserve@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/moduleserve/-/moduleserve-0.9.1.tgz#11bad4337ea248d7eaf10d2c7f8649a8c3b9c1f8" integrity sha512-WF2BeGnM2Ko7bdICgJO+Ibu+ZD33ExJHzOzTDsCUzfZnvnFfheEIYBTWyIqSRU0tXh4UTQ1krDOCglFTJPBMow== @@ -14439,7 +14439,7 @@ react-ace@10.0.0: lodash.isequal "^4.5.0" prop-types "^15.7.2" -react-ace@10.1.0: +react-ace@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-10.1.0.tgz#d348eac2b16475231779070b6cd16768deed565f" integrity sha512-VkvUjZNhdYTuKOKQpMIZi7uzZZVgzCjM7cLYu6F64V0mejY8a2XTyPUIMszC6A4trbeMIHbK5fYFcT/wkP/8VA== @@ -14693,7 +14693,7 @@ react-router@6.3.0, react-router@^6.0.0: dependencies: history "^5.2.0" -react-scripts@5.0.1: +react-scripts@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-5.0.1.tgz#6285dbd65a8ba6e49ca8d651ce30645a6d980003" integrity sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ== From fd957ef40136a708c61940d8b4dd4bacf363d4fb Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Sat, 30 Apr 2022 13:43:46 -0400 Subject: [PATCH 21/26] Mixture last argument can be float --- .../ReducerInterface/ReducerInterface_GenericDistribution.res | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res index 7f5ad1eb..30585395 100644 --- a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res @@ -131,6 +131,7 @@ module Helpers = { | Error(err) => GenDistError(ArgumentError(err)) } } + | Some(EvNumber(_)) | Some(EvDistribution(_)) => switch parseDistributionArray(args) { | Ok(distributions) => mixtureWithDefaultWeights(distributions) From f8f6a1ecc624934c581c4c3dcc35b110fd4566a9 Mon Sep 17 00:00:00 2001 From: Quinn Dougherty Date: Sat, 30 Apr 2022 13:57:41 -0400 Subject: [PATCH 22/26] hotfix: deleted `browser` field of `package.json`s Value: [1e-9 to 1e-5] --- packages/components/package.json | 1 - packages/squiggle-lang/package.json | 1 - .../DistributionOperation/DistributionOperation.res | 4 ++-- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/components/package.json b/packages/components/package.json index fbddaf2c..29c158fc 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -87,7 +87,6 @@ "@types/react": "17.0.43" }, "source": "./src/index.ts", - "browser": "./dist/bundle.js", "main": "./dist/src/index.js", "types": "./dist/src/index.d.ts" } diff --git a/packages/squiggle-lang/package.json b/packages/squiggle-lang/package.json index ab3e0b72..40f7e7c7 100644 --- a/packages/squiggle-lang/package.json +++ b/packages/squiggle-lang/package.json @@ -62,7 +62,6 @@ "webpack-cli": "^4.9.2" }, "source": "./src/js/index.ts", - "browser": "./dist/bundle.js", "main": "./dist/src/js/index.js", "types": "./dist/src/js/index.d.ts" } diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res index 9952c6da..5f07c6a8 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res @@ -154,12 +154,12 @@ let rec run = (~env, functionCallInfo: functionCallInfo): outputType => { ->GenericDist.toPointSet(~xyPointLength, ~sampleCount, ()) ->E.R2.fmap(r => Dist(PointSet(r))) ->OutputLocal.fromResult - | ToDist(Scale(#Logarithm, f)) => + | ToDist(Scale(#Logarithm, f)) => dist ->GenericDist.pointwiseCombinationFloat(~toPointSetFn, ~algebraicCombination=#Logarithm, ~f) ->E.R2.fmap(r => Dist(r)) ->OutputLocal.fromResult - | ToDist(Scale(#Power, f)) => + | ToDist(Scale(#Power, f)) => dist ->GenericDist.pointwiseCombinationFloat(~toPointSetFn, ~algebraicCombination=#Power, ~f) ->E.R2.fmap(r => Dist(r)) From adb3b335ce837630f3b21a1776383f72276a9c45 Mon Sep 17 00:00:00 2001 From: Quinn Dougherty Date: Sat, 30 Apr 2022 13:58:32 -0400 Subject: [PATCH 23/26] 17 increment Value: [1e-10 to 1e-7] --- packages/components/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/package.json b/packages/components/package.json index 29c158fc..4888a0a5 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@quri/squiggle-components", - "version": "0.2.16", + "version": "0.2.17", "license": "MIT", "dependencies": { "@quri/squiggle-lang": "^0.2.8", From 615051d1c61fd45fcbe8df41d49704d9eb726451 Mon Sep 17 00:00:00 2001 From: Quinn Dougherty Date: Sat, 30 Apr 2022 14:10:01 -0400 Subject: [PATCH 24/26] hotfix: brackets in `components/README.md` --- packages/components/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/README.md b/packages/components/README.md index 4d073a14..12cd87a9 100644 --- a/packages/components/README.md +++ b/packages/components/README.md @@ -17,7 +17,7 @@ Add to `App.js`: ```jsx import { SquiggleEditor } from "@quri/squiggle-components"; -; +; ``` # Build storybook for development From 2776a4369302c81b7b4fe8b454971b991afc5e25 Mon Sep 17 00:00:00 2001 From: Quinn Dougherty Date: Sat, 30 Apr 2022 14:10:54 -0400 Subject: [PATCH 25/26] lint --- packages/components/README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/components/README.md b/packages/components/README.md index 12cd87a9..03eb5750 100644 --- a/packages/components/README.md +++ b/packages/components/README.md @@ -17,7 +17,10 @@ Add to `App.js`: ```jsx import { SquiggleEditor } from "@quri/squiggle-components"; -; +; ``` # Build storybook for development From d6cec6886cd1effd80e6a80111ab7d89c66600b7 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Sat, 30 Apr 2022 18:40:18 +0000 Subject: [PATCH 26/26] Clean up the props, removing unused and making some optional --- packages/components/src/components/SquiggleChart.tsx | 2 -- .../components/src/components/SquiggleEditor.tsx | 12 +++--------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/packages/components/src/components/SquiggleChart.tsx b/packages/components/src/components/SquiggleChart.tsx index 31cd9787..699a7e28 100644 --- a/packages/components/src/components/SquiggleChart.tsx +++ b/packages/components/src/components/SquiggleChart.tsx @@ -144,8 +144,6 @@ export interface SquiggleChartProps { diagramStop?: number; /** If the result is a function, how many points along the function it samples */ diagramCount?: number; - /** variables declared before this expression */ - environment?: unknown; /** When the environment changes */ onChange?(expr: squiggleExpression): void; /** CSS width of the element */ diff --git a/packages/components/src/components/SquiggleEditor.tsx b/packages/components/src/components/SquiggleEditor.tsx index 2c01f72f..23686a4f 100644 --- a/packages/components/src/components/SquiggleEditor.tsx +++ b/packages/components/src/components/SquiggleEditor.tsx @@ -32,16 +32,14 @@ export interface SquiggleEditorProps { diagramStop?: number; /** If the result is a function, how many points along the function it samples */ diagramCount?: number; - /** The environment, other variables that were already declared */ - environment?: unknown; /** when the environment changes. Used again for notebook magic*/ onChange?(expr: squiggleExpression): void; /** The width of the element */ - width: number; + width?: number; /** Previous variable declarations */ - bindings: bindings; + bindings?: bindings; /** JS Imports */ - jsImports: jsImports; + jsImports?: jsImports; } const Input = styled.div` @@ -61,7 +59,6 @@ export let SquiggleEditor: React.FC = ({ diagramStop, diagramCount, onChange, - environment, bindings = defaultBindings, jsImports = defaultImports, }: SquiggleEditorProps) => { @@ -87,7 +84,6 @@ export let SquiggleEditor: React.FC = ({ diagramStart={diagramStart} diagramStop={diagramStop} diagramCount={diagramCount} - environment={environment} onChange={onChange} bindings={bindings} jsImports={jsImports} @@ -145,8 +141,6 @@ export interface SquigglePartialProps { diagramCount?: number; /** when the environment changes. Used again for notebook magic*/ onChange?(expr: bindings): void; - /** The width of the element */ - width: number; /** Previously declared variables */ bindings?: bindings; /** Variables imported from js */