From 282fa7726b7c5ff906a9fa1062faa7bfb2fcedb9 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Thu, 28 Apr 2022 21:14:03 -0400 Subject: [PATCH 01/24] 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/24] 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 8217801de33c74b5c7e83eebe635c779c8f118b3 Mon Sep 17 00:00:00 2001 From: Quinn Dougherty Date: Fri, 29 Apr 2022 18:38:55 -0400 Subject: [PATCH 03/24] 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 04/24] 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 05/24] 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 06/24] 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 07/24] 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 08/24] 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 09/24] 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 10/24] 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 11/24] `^`-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 12/24] `^`-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 13/24] 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 14/24] 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 15/24] 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 16/24] 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 17/24] 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 18/24] 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 */ From 76b3adddc4a511a00982b467c1cc7a9e586814de Mon Sep 17 00:00:00 2001 From: Umur Ozkul Date: Mon, 2 May 2022 11:12:12 +0200 Subject: [PATCH 19/24] rename to exampleStatementY --- .../Reducer_Dispatch_BuiltInMacros_test.res | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/squiggle-lang/__tests__/Reducer/Reducer_Dispatch/Reducer_Dispatch_BuiltInMacros_test.res b/packages/squiggle-lang/__tests__/Reducer/Reducer_Dispatch/Reducer_Dispatch_BuiltInMacros_test.res index eb6e6c0d..f0393103 100644 --- a/packages/squiggle-lang/__tests__/Reducer/Reducer_Dispatch/Reducer_Dispatch_BuiltInMacros_test.res +++ b/packages/squiggle-lang/__tests__/Reducer/Reducer_Dispatch/Reducer_Dispatch_BuiltInMacros_test.res @@ -7,7 +7,7 @@ module ExpressionT = Reducer_Expression_T let exampleExpression = eNumber(1.) let exampleExpressionY = eSymbol("y") -let exampleStatement = eLetStatement("y", eNumber(1.)) +let exampleStatementY = eLetStatement("y", eNumber(1.)) let exampleStatementX = eLetStatement("y", eSymbol("x")) let exampleStatementZ = eLetStatement("z", eSymbol("y")) @@ -16,9 +16,9 @@ testMacro([], exampleExpression, "Ok(1)") describe("bindStatement", () => { // A statement is bound by the bindings created by the previous statement - testMacro([], eBindStatement(eBindings([]), exampleStatement), "Ok((:$setBindings {} :y 1))") + testMacro([], eBindStatement(eBindings([]), exampleStatementY), "Ok((:$setBindings {} :y 1))") // Then it answers the bindings for the next statement when reduced - testMacroEval([], eBindStatement(eBindings([]), exampleStatement), "Ok({y: 1})") + testMacroEval([], eBindStatement(eBindings([]), exampleStatementY), "Ok({y: 1})") // Now let's feed a binding to see what happens testMacro( [], @@ -30,7 +30,7 @@ describe("bindStatement", () => { // When bindings from previous statement are missing the context is injected. This must be the first statement of a block testMacro( [("z", EvNumber(99.))], - eBindStatementDefault(exampleStatement), + eBindStatementDefault(exampleStatementY), "Ok((:$setBindings {z: 99} :y 1))", ) }) @@ -41,19 +41,19 @@ describe("bindExpression", () => { // When an let statement is the end expression then bindings are returned testMacro( [], - eBindExpression(eBindings([("x", EvNumber(2.))]), exampleStatement), + eBindExpression(eBindings([("x", EvNumber(2.))]), exampleStatementY), "Ok((:$exportBindings (:$setBindings {x: 2} :y 1)))", ) // Now let's reduce that expression testMacroEval( [], - eBindExpression(eBindings([("x", EvNumber(2.))]), exampleStatement), + eBindExpression(eBindings([("x", EvNumber(2.))]), exampleStatementY), "Ok({x: 2,y: 1})", ) // When bindings are missing the context is injected. This must be the first and last statement of a block testMacroEval( [("z", EvNumber(99.))], - eBindExpressionDefault(exampleStatement), + eBindExpressionDefault(exampleStatementY), "Ok({y: 1,z: 99})", ) }) @@ -63,22 +63,22 @@ describe("block", () => { testMacro([], eBlock(list{exampleExpression}), "Ok((:$$bindExpression 1))") testMacroEval([], eBlock(list{exampleExpression}), "Ok(1)") // Block with a single statement - testMacro([], eBlock(list{exampleStatement}), "Ok((:$$bindExpression (:$let :y 1)))") - testMacroEval([], eBlock(list{exampleStatement}), "Ok({y: 1})") + testMacro([], eBlock(list{exampleStatementY}), "Ok((:$$bindExpression (:$let :y 1)))") + testMacroEval([], eBlock(list{exampleStatementY}), "Ok({y: 1})") // Block with a statement and an expression testMacro( [], - eBlock(list{exampleStatement, exampleExpressionY}), + eBlock(list{exampleStatementY, exampleExpressionY}), "Ok((:$$bindExpression (:$$bindStatement (:$let :y 1)) :y))", ) - testMacroEval([], eBlock(list{exampleStatement, exampleExpressionY}), "Ok(1)") + testMacroEval([], eBlock(list{exampleStatementY, exampleExpressionY}), "Ok(1)") // Block with a statement and another statement testMacro( [], - eBlock(list{exampleStatement, exampleStatementZ}), + eBlock(list{exampleStatementY, exampleStatementZ}), "Ok((:$$bindExpression (:$$bindStatement (:$let :y 1)) (:$let :z :y)))", ) - testMacroEval([], eBlock(list{exampleStatement, exampleStatementZ}), "Ok({y: 1,z: 1})") + testMacroEval([], eBlock(list{exampleStatementY, exampleStatementZ}), "Ok({y: 1,z: 1})") // Block inside a block testMacro( [], From e262f76d9852715290284cc611b37c3fdf4c4a60 Mon Sep 17 00:00:00 2001 From: Umur Ozkul Date: Mon, 2 May 2022 11:20:08 +0200 Subject: [PATCH 20/24] spelling --- .../Reducer_Dispatch/Reducer_Dispatch_BuiltInMacros_test.res | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/squiggle-lang/__tests__/Reducer/Reducer_Dispatch/Reducer_Dispatch_BuiltInMacros_test.res b/packages/squiggle-lang/__tests__/Reducer/Reducer_Dispatch/Reducer_Dispatch_BuiltInMacros_test.res index f0393103..7bbc43dd 100644 --- a/packages/squiggle-lang/__tests__/Reducer/Reducer_Dispatch/Reducer_Dispatch_BuiltInMacros_test.res +++ b/packages/squiggle-lang/__tests__/Reducer/Reducer_Dispatch/Reducer_Dispatch_BuiltInMacros_test.res @@ -11,7 +11,7 @@ let exampleStatementY = eLetStatement("y", eNumber(1.)) let exampleStatementX = eLetStatement("y", eSymbol("x")) let exampleStatementZ = eLetStatement("z", eSymbol("y")) -// If it is not a mactro then it is not expanded +// If it is not a macro then it is not expanded testMacro([], exampleExpression, "Ok(1)") describe("bindStatement", () => { From 6796db82b4d7e7507e228bf2bd416176e1ad6380 Mon Sep 17 00:00:00 2001 From: Umur Ozkul Date: Mon, 2 May 2022 11:38:32 +0200 Subject: [PATCH 21/24] note weird distribution test --- .../ReducerInterface/ReducerInterface_Distribution_test.res | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/squiggle-lang/__tests__/ReducerInterface/ReducerInterface_Distribution_test.res b/packages/squiggle-lang/__tests__/ReducerInterface/ReducerInterface_Distribution_test.res index 2c0cc3e6..bb330479 100644 --- a/packages/squiggle-lang/__tests__/ReducerInterface/ReducerInterface_Distribution_test.res +++ b/packages/squiggle-lang/__tests__/ReducerInterface/ReducerInterface_Distribution_test.res @@ -132,7 +132,8 @@ describe("parse on distribution functions", () => { testParse( ~skip=true, "normal(5,2) .- normal(5,1)", - "Ok((:$$block (:dotPow (:normal 5 2) (:normal 5 1))))", + "Ok((:$$block (:dotSubtract (:normal 5 2) (:normal 5 1))))", + // TODO: !!! returns "Ok((:$$block (:dotPow (:normal 5 2) (:normal 5 1))))" ) testParse( "normal(5,2) .* normal(5,1)", From 087596ec432570bf446117552b000de7ea9d1701 Mon Sep 17 00:00:00 2001 From: Umur Ozkul Date: Mon, 2 May 2022 11:43:09 +0200 Subject: [PATCH 22/24] function trics --- .../__tests__/Reducer/Reducer_functionTricks_test.res | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 packages/squiggle-lang/__tests__/Reducer/Reducer_functionTricks_test.res diff --git a/packages/squiggle-lang/__tests__/Reducer/Reducer_functionTricks_test.res b/packages/squiggle-lang/__tests__/Reducer/Reducer_functionTricks_test.res new file mode 100644 index 00000000..7b6b7097 --- /dev/null +++ b/packages/squiggle-lang/__tests__/Reducer/Reducer_functionTricks_test.res @@ -0,0 +1,6 @@ +open Jest +open Reducer_TestHelpers + +describe("function trics", () => { + testEvalToBe("1", "Ok(1)") +}) \ No newline at end of file From c0fad8c668705ab112b07dc9dd622ef8a366f3d5 Mon Sep 17 00:00:00 2001 From: Umur Ozkul Date: Mon, 2 May 2022 12:10:31 +0200 Subject: [PATCH 23/24] define lambdaValue record as payload --- .../Reducer_Expression_ExpressionBuilder.res | 8 ++++---- .../Reducer_Expression_Lambda.res | 4 ++-- .../ReducerInterface_ExpressionValue.res | 16 ++++++++++------ 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Expression/Reducer_Expression_ExpressionBuilder.res b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Expression/Reducer_Expression_ExpressionBuilder.res index ec3a0214..989d2810 100644 --- a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Expression/Reducer_Expression_ExpressionBuilder.res +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Expression/Reducer_Expression_ExpressionBuilder.res @@ -26,10 +26,10 @@ let eFunction = (fName: string, lispArgs: list): expression => { } let eLambda = (parameters: array, context, expr) => - BExpressionValue.EvLambda( - parameters, - context, - expr->castExpressionToInternalCode, + BExpressionValue.EvLambda({ + parameters: parameters, + context: context, + body: expr->castExpressionToInternalCode} )->BExpressionT.EValue let eNumber = aNumber => aNumber->BExpressionValue.EvNumber->BExpressionT.EValue diff --git a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Expression/Reducer_Expression_Lambda.res b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Expression/Reducer_Expression_Lambda.res index a2d795c0..675e3bc3 100644 --- a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Expression/Reducer_Expression_Lambda.res +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Expression/Reducer_Expression_Lambda.res @@ -30,6 +30,6 @@ let applyParametersToLambda = ( reducer(newExpression, bindings, environment) } -let doLambdaCall = ((parameters, context, internal), args, environment, reducer) => { - applyParametersToLambda(internal, parameters, args, context, environment, reducer) +let doLambdaCall = (lambdaValue: ExpressionValue.lambdaValue, args, environment, reducer) => { + applyParametersToLambda(lambdaValue.body, lambdaValue.parameters, args, lambdaValue.context, environment, reducer) } diff --git a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_ExpressionValue.res b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_ExpressionValue.res index 31168425..ddf2cd48 100644 --- a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_ExpressionValue.res +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_ExpressionValue.res @@ -15,15 +15,19 @@ type rec expressionValue = | EvBool(bool) | EvCall(string) // External function call | EvDistribution(DistributionTypes.genericDist) - | EvLambda((array, record, internalCode)) + | EvLambda(lambdaValue) | EvNumber(float) | EvRecord(record) | EvString(string) | EvSymbol(string) and record = Js.Dict.t +and externalBindings = record +and lambdaValue = { + parameters: array, + context: externalBindings, + body: internalCode, +} -@genType -type externalBindings = record @genType let defaultExternalBindings: externalBindings = Js.Dict.empty() @@ -41,8 +45,8 @@ let rec toString = aValue => } | EvBool(aBool) => Js.String.make(aBool) | EvCall(fName) => `:${fName}` - | EvLambda((parameters, _context, _internalCode)) => - `lambda(${Js.Array2.toString(parameters)}=>internal)` + | EvLambda(lambdaValue) => + `lambda(${Js.Array2.toString(lambdaValue.parameters)}=>internal code)` | EvNumber(aNumber) => Js.String.make(aNumber) | EvString(aString) => `'${aString}'` | EvSymbol(aString) => `:${aString}` @@ -65,7 +69,7 @@ let toStringWithType = aValue => | EvBool(_) => `Bool::${toString(aValue)}` | EvCall(_) => `Call::${toString(aValue)}` | EvDistribution(_) => `Distribution::${toString(aValue)}` - | EvLambda((_parameters, _context, _internalCode)) => `Lambda::${toString(aValue)}` + | EvLambda(_) => `Lambda::${toString(aValue)}` | EvNumber(_) => `Number::${toString(aValue)}` | EvRecord(_) => `Record::${toString(aValue)}` | EvString(_) => `String::${toString(aValue)}` From 1e673e54c33d078beb695de40a4e45dfcffec180 Mon Sep 17 00:00:00 2001 From: Umur Ozkul Date: Mon, 2 May 2022 12:23:37 +0200 Subject: [PATCH 24/24] function tricks test defined (Sam's trials) --- .../Reducer/Reducer_functionTricks_test.res | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/squiggle-lang/__tests__/Reducer/Reducer_functionTricks_test.res b/packages/squiggle-lang/__tests__/Reducer/Reducer_functionTricks_test.res index 7b6b7097..69e20067 100644 --- a/packages/squiggle-lang/__tests__/Reducer/Reducer_functionTricks_test.res +++ b/packages/squiggle-lang/__tests__/Reducer/Reducer_functionTricks_test.res @@ -1,6 +1,17 @@ open Jest open Reducer_TestHelpers -describe("function trics", () => { - testEvalToBe("1", "Ok(1)") +Skip.describe("function trics", () => { + testEvalToBe("f(x,y)=x(y); f(f)", "????") + testEvalToBe("f(x)=x(y); f(f)", "????") + testEvalToBe("f(x)=x; f(f)", "????") + + testEvalToBe("f(x,y)=x(y); f(z)", "????") + testEvalToBe("f(x,y)=x(y); f(2)", "????") //prevent js error + testEvalToBe("f(x)=f(y)=2; f(2)", "????") //prevent multiple assignment + testEvalToBe("f(x)=x+1; g(x)=f(x)+1;g(2)", "????") //TODO: f is not found + testEvalToBe("y=2;g(x)=y+1;g(2)", "????") //TODO : y is not found + testEvalToBe("y=2;g(x)=inspect(y)+1", "????") //TODO : 666 + testEvalToBe("f(x,y)=x+y; f(1,2,3,4)", "????") //TODO : arity)) + testEvalToBe("f(x,y)=x+y; f(1)", "????") //TODO : arity)) }) \ No newline at end of file