diff --git a/packages/components/package.json b/packages/components/package.json index 21b3e46e..67b2eeb5 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -21,10 +21,10 @@ "@storybook/addon-actions": "^6.5.3", "@storybook/addon-essentials": "^6.5.4", "@storybook/addon-links": "^6.5.4", - "@storybook/builder-webpack5": "^6.5.3", + "@storybook/builder-webpack5": "^6.5.4", "@storybook/manager-webpack5": "^6.5.4", "@storybook/node-logger": "^6.5.4", - "@storybook/preset-create-react-app": "^4.1.0", + "@storybook/preset-create-react-app": "^4.1.1", "@storybook/react": "^6.5.4", "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^13.2.0", diff --git a/packages/squiggle-lang/__tests__/ReducerInterface/ReducerInterface_Distribution_test.res b/packages/squiggle-lang/__tests__/ReducerInterface/ReducerInterface_Distribution_test.res index bc95f160..4e2f9aaa 100644 --- a/packages/squiggle-lang/__tests__/ReducerInterface/ReducerInterface_Distribution_test.res +++ b/packages/squiggle-lang/__tests__/ReducerInterface/ReducerInterface_Distribution_test.res @@ -23,7 +23,7 @@ describe("eval on distribution functions", () => { testEval("-normal(5,2)", "Ok(Normal(-5,2))") }) describe("to", () => { - testEval("5 to 2", "Error(Distribution Math Error: Low value must be less than high value.)") + testEval("5 to 2", "Error(TODO: Low value must be less than high value.)") testEval("to(2,5)", "Ok(Lognormal(1.1512925464970227,0.27853260523016377))") testEval("to(-2,2)", "Ok(Normal(0,1.2159136638235384))") }) diff --git a/packages/squiggle-lang/src/rescript/Distributions/GenericDist.res b/packages/squiggle-lang/src/rescript/Distributions/GenericDist.res index 1df10240..d6920a4e 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/GenericDist.res +++ b/packages/squiggle-lang/src/rescript/Distributions/GenericDist.res @@ -31,6 +31,8 @@ let sampleN = (t: t, n) => | SampleSet(r) => SampleSetDist.sampleN(r, n) } +let sample = (t: t) => sampleN(t, 1)->E.A.first |> E.O.toExn("Should not have happened") + let toSampleSetDist = (t: t, n) => SampleSetDist.make(sampleN(t, n))->E.R2.errMap(DistributionTypes.Error.sampleErrorToDistErr) diff --git a/packages/squiggle-lang/src/rescript/Distributions/GenericDist.resi b/packages/squiggle-lang/src/rescript/Distributions/GenericDist.resi index 79fb54ab..fd9afa58 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/GenericDist.resi +++ b/packages/squiggle-lang/src/rescript/Distributions/GenericDist.resi @@ -6,6 +6,7 @@ type scaleMultiplyFn = (t, float) => result type pointwiseAddFn = (t, t) => result let sampleN: (t, int) => array +let sample: t => float let toSampleSetDist: (t, int) => Belt.Result.t diff --git a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Core.res b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Core.res new file mode 100644 index 00000000..99ecc78f --- /dev/null +++ b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Core.res @@ -0,0 +1,301 @@ +type expressionValue = ReducerInterface_ExpressionValue.expressionValue + +/* + Function Registry "Type". A type, without any other information. + Like, #Float +*/ +type rec frType = + | FRTypeNumber + | FRTypeNumeric + | FRTypeDistOrNumber + | FRTypeRecord(frTypeRecord) + | FRTypeArray(array) + | FRTypeOption(frType) +and frTypeRecord = array +and frTypeRecordParam = (string, frType) + +/* + Function Registry "Value". A type, with the information of that type. + Like, #Float(40.0) +*/ +type rec frValue = + | FRValueNumber(float) + | FRValueDist(DistributionTypes.genericDist) + | FRValueOption(option) + | FRValueDistOrNumber(frValueDistOrNumber) + | FRValueRecord(frValueRecord) +and frValueRecord = array +and frValueRecordParam = (string, frValue) +and frValueDistOrNumber = FRValueNumber(float) | FRValueDist(DistributionTypes.genericDist) + +type fnDefinition = { + name: string, + inputs: array, + run: (array, DistributionOperation.env) => result, +} + +type function = { + name: string, + definitions: array, +} + +type registry = array + +module FRType = { + type t = frType + let rec toString = (t: t) => + switch t { + | FRTypeNumber => "number" + | FRTypeNumeric => "numeric" + | FRTypeDistOrNumber => "frValueDistOrNumber" + | FRTypeRecord(r) => { + let input = ((name, frType): frTypeRecordParam) => `${name}: ${toString(frType)}` + `record({${r->E.A2.fmap(input)->E.A2.joinWith(", ")}})` + } + | FRTypeArray(r) => `record(${r->E.A2.fmap(toString)->E.A2.joinWith(", ")})` + | FRTypeOption(v) => `option(${toString(v)})` + } + + let rec matchWithExpressionValue = (t: t, r: expressionValue): option => + switch (t, r) { + | (FRTypeNumber, EvNumber(f)) => Some(FRValueNumber(f)) + | (FRTypeDistOrNumber, EvNumber(f)) => Some(FRValueDistOrNumber(FRValueNumber(f))) + | (FRTypeDistOrNumber, EvDistribution(Symbolic(#Float(f)))) => + Some(FRValueDistOrNumber(FRValueNumber(f))) + | (FRTypeDistOrNumber, EvDistribution(f)) => Some(FRValueDistOrNumber(FRValueDist(f))) + | (FRTypeNumeric, EvNumber(f)) => Some(FRValueNumber(f)) + | (FRTypeNumeric, EvDistribution(Symbolic(#Float(f)))) => Some(FRValueNumber(f)) + | (FRTypeOption(v), _) => Some(FRValueOption(matchWithExpressionValue(v, r))) + | (FRTypeRecord(recordParams), EvRecord(record)) => { + let getAndMatch = (name, input) => + E.Dict.get(record, name)->E.O.bind(matchWithExpressionValue(input)) + //All names in the type must be present. If any are missing, the corresponding + //value will be None, and this function would return None. + let namesAndValues: array> = + recordParams->E.A2.fmap(((name, input)) => + getAndMatch(name, input)->E.O2.fmap(match => (name, match)) + ) + namesAndValues->E.A.O.openIfAllSome->E.O2.fmap(r => FRValueRecord(r)) + } + | _ => None + } + + let matchWithExpressionValueArray = (inputs: array, args: array): option< + array, + > => { + let isSameLength = E.A.length(inputs) == E.A.length(args) + if !isSameLength { + None + } else { + E.A.zip(inputs, args) + ->E.A2.fmap(((input, arg)) => matchWithExpressionValue(input, arg)) + ->E.A.O.openIfAllSome + } + } +} + +/* + This module, Matcher, is fairly lengthy. However, only two functions from it + are meant to be used outside of it. These are findMatches and matchToDef in Matches.Registry. + The rest of it is just called from those two functions. +*/ +module Matcher = { + module MatchSimple = { + type t = DifferentName | SameNameDifferentArguments | FullMatch + + let isFullMatch = (match: t) => + switch match { + | FullMatch => true + | _ => false + } + + let isNameMatchOnly = (match: t) => + switch match { + | SameNameDifferentArguments => true + | _ => false + } + } + + module Match = { + type t<'a, 'b> = DifferentName | SameNameDifferentArguments('a) | FullMatch('b) + + let isFullMatch = (match: t<'a, 'b>): bool => + switch match { + | FullMatch(_) => true + | _ => false + } + + let isNameMatchOnly = (match: t<'a, 'b>) => + switch match { + | SameNameDifferentArguments(_) => true + | _ => false + } + } + + module FnDefinition = { + let matchAssumingSameName = (f: fnDefinition, args: array) => { + switch FRType.matchWithExpressionValueArray(f.inputs, args) { + | Some(_) => MatchSimple.FullMatch + | None => MatchSimple.SameNameDifferentArguments + } + } + + let match = (f: fnDefinition, fnName: string, args: array) => { + if f.name !== fnName { + MatchSimple.DifferentName + } else { + matchAssumingSameName(f, args) + } + } + } + + module Function = { + type definitionId = int + type match = Match.t, definitionId> + + let match = (f: function, fnName: string, args: array): match => { + let matchedDefinition = () => + E.A.getIndexBy(f.definitions, r => + MatchSimple.isFullMatch(FnDefinition.match(r, fnName, args)) + ) |> E.O.fmap(r => Match.FullMatch(r)) + let getMatchedNameOnlyDefinition = () => { + let nameMatchIndexes = + f.definitions + ->E.A2.fmapi((index, r) => + MatchSimple.isNameMatchOnly(FnDefinition.match(r, fnName, args)) ? Some(index) : None + ) + ->E.A.O.concatSomes + switch nameMatchIndexes { + | [] => None + | elements => Some(Match.SameNameDifferentArguments(elements)) + } + } + + E.A.O.firstSomeFnWithDefault( + [matchedDefinition, getMatchedNameOnlyDefinition], + Match.DifferentName, + ) + } + } + + module RegistryMatch = { + type match = { + fnName: string, + inputIndex: int, + } + let makeMatch = (fnName: string, inputIndex: int) => {fnName: fnName, inputIndex: inputIndex} + } + + module Registry = { + let _findExactMatches = (r: registry, fnName: string, args: array) => { + let functionMatchPairs = r->E.A2.fmap(l => (l, Function.match(l, fnName, args))) + let fullMatch = functionMatchPairs->E.A.getBy(((_, match)) => Match.isFullMatch(match)) + fullMatch->E.O.bind(((fn, match)) => + switch match { + | FullMatch(index) => Some(RegistryMatch.makeMatch(fn.name, index)) + | _ => None + } + ) + } + + let _findNameMatches = (r: registry, fnName: string, args: array) => { + let functionMatchPairs = r->E.A2.fmap(l => (l, Function.match(l, fnName, args))) + let getNameMatches = + functionMatchPairs + ->E.A2.fmap(((fn, match)) => Match.isNameMatchOnly(match) ? Some((fn, match)) : None) + ->E.A.O.concatSomes + let matches = + getNameMatches + ->E.A2.fmap(((fn, match)) => + switch match { + | SameNameDifferentArguments(indexes) => + indexes->E.A2.fmap(index => RegistryMatch.makeMatch(fn.name, index)) + | _ => [] + } + ) + ->Belt.Array.concatMany + E.A.toNoneIfEmpty(matches) + } + + let findMatches = (r: registry, fnName: string, args: array) => { + switch _findExactMatches(r, fnName, args) { + | Some(r) => Match.FullMatch(r) + | None => + switch _findNameMatches(r, fnName, args) { + | Some(r) => Match.SameNameDifferentArguments(r) + | None => Match.DifferentName + } + } + } + + let matchToDef = (registry: registry, {fnName, inputIndex}: RegistryMatch.match): option< + fnDefinition, + > => + registry + ->E.A.getBy(fn => fn.name === fnName) + ->E.O.bind(fn => E.A.get(fn.definitions, inputIndex)) + } +} + +module FnDefinition = { + type t = fnDefinition + + let toString = (t: t) => { + let inputs = t.inputs->E.A2.fmap(FRType.toString)->E.A2.joinWith(", ") + t.name ++ `(${inputs})` + } + + let run = (t: t, args: array, env: DistributionOperation.env) => { + let argValues = FRType.matchWithExpressionValueArray(t.inputs, args) + switch argValues { + | Some(values) => t.run(values, env) + | None => Error("Incorrect Types") + } + } + + let make = (~name, ~inputs, ~run): t => { + name: name, + inputs: inputs, + run: run, + } +} + +module Function = { + type t = function + + let make = (~name, ~definitions): t => { + name: name, + definitions: definitions, + } +} + +module Registry = { + /* + There's a (potential+minor) bug here: If a function definition is called outside of the calls + to the registry, then it's possible that there could be a match after the registry is + called. However, for now, we could just call the registry last. + */ + let matchAndRun = ( + ~registry: registry, + ~fnName: string, + ~args: array, + ~env: DistributionOperation.env, + ) => { + let matchToDef = m => Matcher.Registry.matchToDef(registry, m) + let showNameMatchDefinitions = matches => { + let defs = + matches + ->E.A2.fmap(matchToDef) + ->E.A.O.concatSomes + ->E.A2.fmap(FnDefinition.toString) + ->E.A2.fmap(r => `[${r}]`) + ->E.A2.joinWith("; ") + `There are function matches for ${fnName}(), but with different arguments: ${defs}` + } + switch Matcher.Registry.findMatches(registry, fnName, args) { + | Matcher.Match.FullMatch(match) => match->matchToDef->E.O2.fmap(FnDefinition.run(_, args, env)) + | SameNameDifferentArguments(m) => Some(Error(showNameMatchDefinitions(m))) + | _ => None + } + } +} diff --git a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Core.resi b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Core.resi new file mode 100644 index 00000000..5ca8c708 --- /dev/null +++ b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Core.resi @@ -0,0 +1,58 @@ +type expressionValue = ReducerInterface_ExpressionValue.expressionValue + +type rec frType = + | FRTypeNumber + | FRTypeNumeric + | FRTypeDistOrNumber + | FRTypeRecord(frTypeRecord) + | FRTypeArray(array) + | FRTypeOption(frType) +and frTypeRecord = array +and frTypeRecordParam = (string, frType) + +type rec frValue = + | FRValueNumber(float) + | FRValueDist(DistributionTypes.genericDist) + | FRValueOption(option) + | FRValueDistOrNumber(frValueDistOrNumber) + | FRValueRecord(frValueRecord) +and frValueRecord = array +and frValueRecordParam = (string, frValue) +and frValueDistOrNumber = FRValueNumber(float) | FRValueDist(DistributionTypes.genericDist) + +type fnDefinition = { + name: string, + inputs: array, + run: (array, DistributionOperation.env) => result, +} + +type function = { + name: string, + definitions: array, +} + +type registry = array + +// Note: The function "name" is just used for documentation purposes +module Function: { + type t = function + let make: (~name: string, ~definitions: array) => t +} + +module FnDefinition: { + type t = fnDefinition + let make: ( + ~name: string, + ~inputs: array, + ~run: (array, DistributionOperation.env) => result, + ) => t +} + +module Registry: { + let matchAndRun: ( + ~registry: registry, + ~fnName: string, + ~args: array, + ~env: QuriSquiggleLang.DistributionOperation.env, + ) => option> +} diff --git a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Helpers.res b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Helpers.res new file mode 100644 index 00000000..118a15d2 --- /dev/null +++ b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Helpers.res @@ -0,0 +1,156 @@ +open FunctionRegistry_Core + +let impossibleError = "Wrong inputs / Logically impossible" + +module Wrappers = { + let symbolic = r => DistributionTypes.Symbolic(r) + let evDistribution = r => ReducerInterface_ExpressionValue.EvDistribution(r) + let symbolicEvDistribution = r => r->DistributionTypes.Symbolic->evDistribution +} + +module Prepare = { + type ts = array + type err = string + + module ToValueArray = { + module Record = { + let twoArgs = (inputs: ts): result => + switch inputs { + | [FRValueRecord([(_, n1), (_, n2)])] => Ok([n1, n2]) + | _ => Error(impossibleError) + } + } + } + + module ToValueTuple = { + let twoDistOrNumber = (values: ts): result<(frValueDistOrNumber, frValueDistOrNumber), err> => { + switch values { + | [FRValueDistOrNumber(a1), FRValueDistOrNumber(a2)] => Ok(a1, a2) + | _ => Error(impossibleError) + } + } + + let oneDistOrNumber = (values: ts): result => { + switch values { + | [FRValueDistOrNumber(a1)] => Ok(a1) + | _ => Error(impossibleError) + } + } + + module Record = { + let twoDistOrNumber = (values: ts): result<(frValueDistOrNumber, frValueDistOrNumber), err> => + values->ToValueArray.Record.twoArgs->E.R.bind(twoDistOrNumber) + } + } +} + +module Process = { + module DistOrNumberToDist = { + module Helpers = { + let toSampleSet = (r, env: DistributionOperation.env) => + GenericDist.toSampleSetDist(r, env.sampleCount) + + let mapFnResult = r => + switch r { + | Ok(r) => Ok(GenericDist.sample(r)) + | Error(r) => Error(Operation.Other(r)) + } + + let wrapSymbolic = (fn, r) => r->fn->E.R2.fmap(Wrappers.symbolic) + + let singleVarSample = (dist, fn, env) => { + switch toSampleSet(dist, env) { + | Ok(dist) => + switch SampleSetDist.samplesMap(~fn=f => fn(f)->mapFnResult, dist) { + | Ok(r) => Ok(DistributionTypes.SampleSet(r)) + | Error(r) => Error(DistributionTypes.Error.toString(DistributionTypes.SampleSetError(r))) + } + | Error(r) => Error(DistributionTypes.Error.toString(r)) + } + } + + let twoVarSample = (dist1, dist2, fn, env) => { + let altFn = (a, b) => fn((a, b))->mapFnResult + switch E.R.merge(toSampleSet(dist1, env), toSampleSet(dist2, env)) { + | Ok((t1, t2)) => + switch SampleSetDist.map2(~fn=altFn, ~t1, ~t2) { + | Ok(r) => Ok(DistributionTypes.SampleSet(r)) + | Error(r) => Error(Operation.Error.toString(r)) + } + | Error(r) => Error(DistributionTypes.Error.toString(r)) + } + } + } + + let oneValue = ( + ~fn: float => result, + ~value: frValueDistOrNumber, + ~env: DistributionOperation.env, + ): result => { + switch value { + | FRValueNumber(a1) => fn(a1) + | FRValueDist(a1) => Helpers.singleVarSample(a1, r => fn(r), env) + } + } + + let oneValueUsingSymbolicDist = (~fn, ~value) => oneValue(~fn=Helpers.wrapSymbolic(fn), ~value) + + let twoValues = ( + ~fn: ((float, float)) => result, + ~values: (frValueDistOrNumber, frValueDistOrNumber), + ~env: DistributionOperation.env, + ): result => { + switch values { + | (FRValueNumber(a1), FRValueNumber(a2)) => fn((a1, a2)) + | (FRValueDist(a1), FRValueNumber(a2)) => Helpers.singleVarSample(a1, r => fn((r, a2)), env) + | (FRValueNumber(a1), FRValueDist(a2)) => Helpers.singleVarSample(a2, r => fn((a1, r)), env) + | (FRValueDist(a1), FRValueDist(a2)) => Helpers.twoVarSample(a1, a2, fn, env) + } + } + + let twoValuesUsingSymbolicDist = (~fn, ~values) => + twoValues(~fn=Helpers.wrapSymbolic(fn), ~values) + } +} + +module TwoArgDist = { + let process = (~fn, ~env, r) => + r + ->E.R.bind(Process.DistOrNumberToDist.twoValuesUsingSymbolicDist(~fn, ~values=_, ~env)) + ->E.R2.fmap(Wrappers.evDistribution) + + let make = (name, fn) => { + FnDefinition.make(~name, ~inputs=[FRTypeDistOrNumber, FRTypeDistOrNumber], ~run=(inputs, env) => + inputs->Prepare.ToValueTuple.twoDistOrNumber->process(~fn, ~env) + ) + } + + let makeRecordP5P95 = (name, fn) => { + FnDefinition.make( + ~name, + ~inputs=[FRTypeRecord([("p5", FRTypeDistOrNumber), ("p95", FRTypeDistOrNumber)])], + ~run=(inputs, env) => inputs->Prepare.ToValueTuple.Record.twoDistOrNumber->process(~fn, ~env), + ) + } + + let makeRecordMeanStdev = (name, fn) => { + FnDefinition.make( + ~name, + ~inputs=[FRTypeRecord([("mean", FRTypeDistOrNumber), ("stdev", FRTypeDistOrNumber)])], + ~run=(inputs, env) => inputs->Prepare.ToValueTuple.Record.twoDistOrNumber->process(~fn, ~env), + ) + } +} + +module OneArgDist = { + let process = (~fn, ~env, r) => + r + ->E.R.bind(Process.DistOrNumberToDist.oneValueUsingSymbolicDist(~fn, ~value=_, ~env)) + ->E.R2.fmap(Wrappers.evDistribution) + + let make = (name, fn) => { + FnDefinition.make(~name, ~inputs=[FRTypeDistOrNumber], ~run=(inputs, env) => + inputs->Prepare.ToValueTuple.oneDistOrNumber->process(~fn, ~env) + ) + } +} diff --git a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Library.res b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Library.res new file mode 100644 index 00000000..43be7118 --- /dev/null +++ b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Library.res @@ -0,0 +1,65 @@ +open FunctionRegistry_Core +open FunctionRegistry_Helpers + +let twoArgs = E.Tuple2.toFnCall + +let registry = [ + Function.make( + ~name="Normal", + ~definitions=[ + TwoArgDist.make("normal", twoArgs(SymbolicDist.Normal.make)), + TwoArgDist.makeRecordP5P95("normal", r => + twoArgs(SymbolicDist.Normal.from90PercentCI, r)->Ok + ), + TwoArgDist.makeRecordMeanStdev("normal", twoArgs(SymbolicDist.Normal.make)), + ], + ), + Function.make( + ~name="Lognormal", + ~definitions=[ + TwoArgDist.make("lognormal", twoArgs(SymbolicDist.Lognormal.make)), + TwoArgDist.makeRecordP5P95("lognormal", r => + twoArgs(SymbolicDist.Lognormal.from90PercentCI, r)->Ok + ), + TwoArgDist.makeRecordMeanStdev("lognormal", twoArgs(SymbolicDist.Lognormal.fromMeanAndStdev)), + ], + ), + Function.make( + ~name="Uniform", + ~definitions=[TwoArgDist.make("uniform", twoArgs(SymbolicDist.Uniform.make))], + ), + Function.make( + ~name="Beta", + ~definitions=[TwoArgDist.make("beta", twoArgs(SymbolicDist.Beta.make))], + ), + Function.make( + ~name="Cauchy", + ~definitions=[TwoArgDist.make("cauchy", twoArgs(SymbolicDist.Cauchy.make))], + ), + Function.make( + ~name="Gamma", + ~definitions=[TwoArgDist.make("gamma", twoArgs(SymbolicDist.Gamma.make))], + ), + Function.make( + ~name="Logistic", + ~definitions=[TwoArgDist.make("logistic", twoArgs(SymbolicDist.Logistic.make))], + ), + Function.make( + ~name="To", + ~definitions=[ + TwoArgDist.make("to", twoArgs(SymbolicDist.From90thPercentile.make)), + TwoArgDist.make( + "credibleIntervalToDistribution", + twoArgs(SymbolicDist.From90thPercentile.make), + ), + ], + ), + Function.make( + ~name="Exponential", + ~definitions=[OneArgDist.make("exponential", SymbolicDist.Exponential.make)], + ), + Function.make( + ~name="Bernoulli", + ~definitions=[OneArgDist.make("bernoulli", SymbolicDist.Bernoulli.make)], + ), +] diff --git a/packages/squiggle-lang/src/rescript/FunctionRegistry/README.md b/packages/squiggle-lang/src/rescript/FunctionRegistry/README.md new file mode 100644 index 00000000..e974b189 --- /dev/null +++ b/packages/squiggle-lang/src/rescript/FunctionRegistry/README.md @@ -0,0 +1,46 @@ +# Function Registry + +The function registry is a library for organizing function definitions. + +The main interface is fairly constrained. Basically, write functions like the following, and add them to a big array. + +```rescript + Function.make( + ~name="Normal", + ~definitions=[ + FnDefinition.make( + ~name="Normal", + ~definitions=[ + FnDefinition.make(~name="normal", ~inputs=[FRTypeDistOrNumber, FRTypeDistOrNumber], ~run=( + inputs, + env, + ) => + inputs + ->Prepare.ToValueTuple.twoDistOrNumber + ->E.R.bind( + Process.twoDistsOrNumbersToDistUsingSymbolicDist( + ~fn=E.Tuple2.toFnCall(SymbolicDist.Normal.make), + ~env, + ~values=_, + ), + ) + ->E.R2.fmap(Wrappers.evDistribution) + ), + ], + ) + ], + ) +``` + +The Function name is just there for future documentation. The function defintions + +## Key Files + +**FunctionRegistry_Core** +Key types, internal functionality, and a `Registry` module with a `matchAndRun` function to call function definitions. + +**FunctionRegistry_Library** +A list of all the Functions defined in the Function Registry. + +**FunctionRegistry_Helpers** +A list of helper functions for the FunctionRegistry_Library. diff --git a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res index fa152c6f..dc827805 100644 --- a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res @@ -179,27 +179,6 @@ module Helpers = { } module SymbolicConstructors = { - let oneFloat = name => - switch name { - | "exponential" => Ok(SymbolicDist.Exponential.make) - | "bernoulli" => Ok(SymbolicDist.Bernoulli.make) - | _ => Error("Unreachable state") - } - - let twoFloat = name => - switch name { - | "beta" => Ok(SymbolicDist.Beta.make) - | "cauchy" => Ok(SymbolicDist.Cauchy.make) - | "credibleIntervalToDistribution" => Ok(SymbolicDist.From90thPercentile.make) - | "gamma" => Ok(SymbolicDist.Gamma.make) - | "logistic" => Ok(SymbolicDist.Logistic.make) - | "lognormal" => Ok(SymbolicDist.Lognormal.make) - | "normal" => Ok(SymbolicDist.Normal.make) - | "to" => Ok(SymbolicDist.From90thPercentile.make) // as credibleIntervalToDistribution is defined "to" might be redundant - | "uniform" => Ok(SymbolicDist.Uniform.make) - | _ => Error("Unreachable state") - } - let threeFloat = name => switch name { | "triangular" => Ok(SymbolicDist.Triangular.make) @@ -221,27 +200,8 @@ let dispatchToGenericOutput = ( ): option => { let (fnName, args) = call switch (fnName, args) { - | (("exponential" | "bernoulli") as fnName, [EvNumber(f)]) => - SymbolicConstructors.oneFloat(fnName) - ->E.R.bind(r => r(f)) - ->SymbolicConstructors.symbolicResultToOutput | ("delta", [EvNumber(f)]) => SymbolicDist.Float.makeSafe(f)->SymbolicConstructors.symbolicResultToOutput - | ( - ("normal" - | "uniform" - | "beta" - | "lognormal" - | "cauchy" - | "gamma" - | "credibleIntervalToDistribution" - | "to" - | "logistic") as fnName, - [EvNumber(f1), EvNumber(f2)], - ) => - SymbolicConstructors.twoFloat(fnName) - ->E.R.bind(r => r(f1, f2)) - ->SymbolicConstructors.symbolicResultToOutput | ("triangular" as fnName, [EvNumber(f1), EvNumber(f2), EvNumber(f3)]) => SymbolicConstructors.threeFloat(fnName) ->E.R.bind(r => r(f1, f2, f3)) @@ -390,6 +350,20 @@ let genericOutputToReducerValue = (o: DistributionOperation.outputType): result< | GenDistError(err) => Error(REDistributionError(err)) } -let dispatch = (call, environment) => { - dispatchToGenericOutput(call, environment)->E.O2.fmap(genericOutputToReducerValue) +// I expect that it's important to build this first, so it doesn't get recalculated for each tryRegistry() call. +let registry = FunctionRegistry_Library.registry + +let tryRegistry = ((fnName, args): ExpressionValue.functionCall, env) => { + FunctionRegistry_Core.Registry.matchAndRun(~registry, ~fnName, ~args, ~env)->E.O2.fmap( + E.R2.errMap(_, s => Reducer_ErrorValue.RETodo(s)), + ) +} + +let dispatch = (call: ExpressionValue.functionCall, environment) => { + let regularDispatch = + dispatchToGenericOutput(call, environment)->E.O2.fmap(genericOutputToReducerValue) + switch regularDispatch { + | Some(x) => Some(x) + | None => tryRegistry(call, environment) + } } diff --git a/packages/squiggle-lang/src/rescript/Utility/E.res b/packages/squiggle-lang/src/rescript/Utility/E.res index b08754ef..3357f4f4 100644 --- a/packages/squiggle-lang/src/rescript/Utility/E.res +++ b/packages/squiggle-lang/src/rescript/Utility/E.res @@ -2,6 +2,9 @@ Some functions from modules `L`, `O`, and `R` below were copied directly from running `rescript convert -all` on Rationale https://github.com/jonlaing/rationale */ + +let equals = (a, b) => a === b + module FloatFloatMap = { module Id = Belt.Id.MakeComparable({ type t = float @@ -49,6 +52,7 @@ module Tuple2 = { let (_, b) = v b } + let toFnCall = (fn, (a1, a2)) => fn(a1, a2) } module O = { @@ -525,6 +529,7 @@ module A = { let unsafe_get = Array.unsafe_get let get = Belt.Array.get let getBy = Belt.Array.getBy + let getIndexBy = Belt.Array.getIndexBy let last = a => get(a, length(a) - 1) let first = get(_, 0) let hasBy = (r, fn) => Belt.Array.getBy(r, fn) |> O.isSome @@ -538,6 +543,7 @@ module A = { let reducei = Belt.Array.reduceWithIndex let isEmpty = r => length(r) < 1 let stableSortBy = Belt.SortArray.stableSortBy + let toNoneIfEmpty = r => isEmpty(r) ? None : Some(r) let toRanges = (a: array<'a>) => switch a |> Belt.Array.length { | 0 @@ -552,6 +558,12 @@ module A = { |> (x => Ok(x)) } + let getByOpen = (a, op, bin) => + switch getBy(a, r => bin(op(r))) { + | Some(r) => Some(op(r)) + | None => None + } + let tail = Belt.Array.sliceToEnd(_, 1) let zip = Belt.Array.zip @@ -636,6 +648,19 @@ module A = { } } let firstSome = x => Belt.Array.getBy(x, O.isSome) + + let firstSomeFn = (r: array option<'a>>): option<'a> => + O.flatten(getByOpen(r, l => l(), O.isSome)) + + let firstSomeFnWithDefault = (r, default) => firstSomeFn(r)->O2.default(default) + + let openIfAllSome = (optionals: array>): option> => { + if all(O.isSome, optionals) { + Some(optionals |> fmap(O.toExn("Warning: This should not have happened"))) + } else { + None + } + } } module R = { @@ -822,6 +847,7 @@ module A = { module A2 = { let fmap = (a, b) => A.fmap(b, a) + let fmapi = (a, b) => A.fmapi(b, a) let joinWith = (a, b) => A.joinWith(b, a) let filter = (a, b) => A.filter(b, a) } @@ -833,3 +859,9 @@ module JsArray = { |> Js.Array.map(O.toExn("Warning: This should not have happened")) let filter = Js.Array.filter } + +module Dict = { + type t<'a> = Js.Dict.t<'a> + let get = Js.Dict.get + let keys = Js.Dict.keys +} diff --git a/packages/squiggle-lang/src/rescript/Utility/Operation.res b/packages/squiggle-lang/src/rescript/Utility/Operation.res index 7972b2fa..6476850d 100644 --- a/packages/squiggle-lang/src/rescript/Utility/Operation.res +++ b/packages/squiggle-lang/src/rescript/Utility/Operation.res @@ -58,6 +58,7 @@ type operationError = | SampleMapNeedsNtoNFunction | PdfInvalidError | NotYetImplemented // should be removed when `klDivergence` for mixed and discrete is implemented. + | Other(string) @genType module Error = { @@ -73,6 +74,7 @@ module Error = { | SampleMapNeedsNtoNFunction => "SampleMap needs a function that converts a number to a number" | PdfInvalidError => "This Pdf is invalid" | NotYetImplemented => "This pathway is not yet implemented" + | Other(t) => t } } diff --git a/yarn.lock b/yarn.lock index c59717f6..39329f75 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2923,23 +2923,6 @@ prop-types "^15.7.2" regenerator-runtime "^0.13.7" -"@storybook/addons@6.5.3": - version "6.5.3" - resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-6.5.3.tgz#43dd276417edf74be0c465b968d35795f8cd994d" - integrity sha512-gzzkxZ7R4+EaEzIEBbTWmkA55JDEDQrDjg3nNY/SJklnRigYdStz41KSPx6HGkF2CaI5BYVd5vZCawYvG16gyg== - dependencies: - "@storybook/api" "6.5.3" - "@storybook/channels" "6.5.3" - "@storybook/client-logger" "6.5.3" - "@storybook/core-events" "6.5.3" - "@storybook/csf" "0.0.2--canary.4566f4d.1" - "@storybook/router" "6.5.3" - "@storybook/theming" "6.5.3" - "@types/webpack-env" "^1.16.0" - core-js "^3.8.2" - global "^4.4.0" - regenerator-runtime "^0.13.7" - "@storybook/addons@6.5.4": version "6.5.4" resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-6.5.4.tgz#10cf41ab8aa3c509963599092fe8f3cf9a15edb6" @@ -2957,29 +2940,6 @@ global "^4.4.0" regenerator-runtime "^0.13.7" -"@storybook/api@6.5.3": - version "6.5.3" - resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.5.3.tgz#f4c468f348bf6ac65dc571f3e65d67302323312c" - integrity sha512-neVW47ssdG3MqwNwTLjlifS/u6zGUkkcK7G/PC1tnQPP9Zc97BStIqS1RnPGie1iawIAT5ZJQefPGJMneSTBKA== - dependencies: - "@storybook/channels" "6.5.3" - "@storybook/client-logger" "6.5.3" - "@storybook/core-events" "6.5.3" - "@storybook/csf" "0.0.2--canary.4566f4d.1" - "@storybook/router" "6.5.3" - "@storybook/semver" "^7.3.2" - "@storybook/theming" "6.5.3" - core-js "^3.8.2" - fast-deep-equal "^3.1.3" - global "^4.4.0" - lodash "^4.17.21" - memoizerific "^1.11.3" - regenerator-runtime "^0.13.7" - store2 "^2.12.0" - telejson "^6.0.8" - ts-dedent "^2.0.0" - util-deprecate "^1.0.2" - "@storybook/api@6.5.4": version "6.5.4" resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.5.4.tgz#faa06cde4990fd3b2be551ff869fc44a80e66e53" @@ -3056,27 +3016,27 @@ webpack-hot-middleware "^2.25.1" webpack-virtual-modules "^0.2.2" -"@storybook/builder-webpack5@^6.5.3": - version "6.5.3" - resolved "https://registry.yarnpkg.com/@storybook/builder-webpack5/-/builder-webpack5-6.5.3.tgz#1fd01ea93b169afccafcc4f9d6fb15ad992e6ffd" - integrity sha512-noVd6eJE7pmBl886TahPuUdLiVkyE9ecqQhcltnZfMBCuJXeEev0/E642HRp5P2hE6uE2pBzkTAy8gaHExeY+Q== +"@storybook/builder-webpack5@^6.5.4": + version "6.5.4" + resolved "https://registry.yarnpkg.com/@storybook/builder-webpack5/-/builder-webpack5-6.5.4.tgz#bc5b87848d3b8a854b5fe29a2f646184431075d4" + integrity sha512-BoqQkgnyqwySEcfaDreBG9SUnGTzp8jcfdUPqewtqyJK5qQgh79v2VowpSxT00G+eyWcsDkct2U4JnTmjrDpDg== dependencies: "@babel/core" "^7.12.10" - "@storybook/addons" "6.5.3" - "@storybook/api" "6.5.3" - "@storybook/channel-postmessage" "6.5.3" - "@storybook/channels" "6.5.3" - "@storybook/client-api" "6.5.3" - "@storybook/client-logger" "6.5.3" - "@storybook/components" "6.5.3" - "@storybook/core-common" "6.5.3" - "@storybook/core-events" "6.5.3" - "@storybook/node-logger" "6.5.3" - "@storybook/preview-web" "6.5.3" - "@storybook/router" "6.5.3" + "@storybook/addons" "6.5.4" + "@storybook/api" "6.5.4" + "@storybook/channel-postmessage" "6.5.4" + "@storybook/channels" "6.5.4" + "@storybook/client-api" "6.5.4" + "@storybook/client-logger" "6.5.4" + "@storybook/components" "6.5.4" + "@storybook/core-common" "6.5.4" + "@storybook/core-events" "6.5.4" + "@storybook/node-logger" "6.5.4" + "@storybook/preview-web" "6.5.4" + "@storybook/router" "6.5.4" "@storybook/semver" "^7.3.2" - "@storybook/store" "6.5.3" - "@storybook/theming" "6.5.3" + "@storybook/store" "6.5.4" + "@storybook/theming" "6.5.4" "@types/node" "^14.0.10 || ^16.0.0" babel-loader "^8.0.0" babel-plugin-named-exports-order "^0.0.2" @@ -3100,19 +3060,6 @@ webpack-hot-middleware "^2.25.1" webpack-virtual-modules "^0.4.1" -"@storybook/channel-postmessage@6.5.3": - version "6.5.3" - resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-6.5.3.tgz#c3762b92e87cb15e3a3c50d8a23ddede80a1e6d0" - integrity sha512-1vsKhFuTX53VmRm4ZKae+9z6FciSTyywZJ5cYmH2nTRWqW5GOm3UndixHzXpddVM1DWdEH4jJ/Cn15SzPRWiPg== - dependencies: - "@storybook/channels" "6.5.3" - "@storybook/client-logger" "6.5.3" - "@storybook/core-events" "6.5.3" - core-js "^3.8.2" - global "^4.4.0" - qs "^6.10.0" - telejson "^6.0.8" - "@storybook/channel-postmessage@6.5.4": version "6.5.4" resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-6.5.4.tgz#246483250e0e538d7455630d560149b1e974c5d3" @@ -3137,15 +3084,6 @@ global "^4.4.0" telejson "^6.0.8" -"@storybook/channels@6.5.3": - version "6.5.3" - resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-6.5.3.tgz#d1c94f1760a27026d16705ab28a82e582cf9f2d5" - integrity sha512-wpxnMt5clUy+04o+I5LVMoQkYt7nc0e5PDz+pAtlNOvQaoFvlC7oQqsVYxxs1cYm6ZGqAJcsfecI5COtnQfT1w== - dependencies: - core-js "^3.8.2" - ts-dedent "^2.0.0" - util-deprecate "^1.0.2" - "@storybook/channels@6.5.4": version "6.5.4" resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-6.5.4.tgz#a3fdc20d45cf4aa74b5310e5e4eb111e353a408a" @@ -3155,32 +3093,6 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/client-api@6.5.3": - version "6.5.3" - resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-6.5.3.tgz#ca7b5ddb9e745b1485d8946dd14d1e81173dd712" - integrity sha512-BxksIgSDkkt9muA41VbsSB96/u3HJAWuOJw+GCzt0yHmlBgfb3+GpQOJUDqTluWQlojg0DHJhAKgYKbejyEpIA== - dependencies: - "@storybook/addons" "6.5.3" - "@storybook/channel-postmessage" "6.5.3" - "@storybook/channels" "6.5.3" - "@storybook/client-logger" "6.5.3" - "@storybook/core-events" "6.5.3" - "@storybook/csf" "0.0.2--canary.4566f4d.1" - "@storybook/store" "6.5.3" - "@types/qs" "^6.9.5" - "@types/webpack-env" "^1.16.0" - core-js "^3.8.2" - fast-deep-equal "^3.1.3" - global "^4.4.0" - lodash "^4.17.21" - memoizerific "^1.11.3" - qs "^6.10.0" - regenerator-runtime "^0.13.7" - store2 "^2.12.0" - synchronous-promise "^2.0.15" - ts-dedent "^2.0.0" - util-deprecate "^1.0.2" - "@storybook/client-api@6.5.4": version "6.5.4" resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-6.5.4.tgz#e79418ffb21857deb98f5b7fd88dfe23ef12cfe7" @@ -3207,14 +3119,6 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/client-logger@6.5.3": - version "6.5.3" - resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-6.5.3.tgz#4794e87d85c03aa6e38efc4c5775b9680cc1bf23" - integrity sha512-gUJUkDzQdOQBfAQSJffKlZQ6ueUANjTN6u4xA/FIfJM7+I5N43UuS3dFGEjcnZISS5sj7765ct2aZinMzf1NNQ== - dependencies: - core-js "^3.8.2" - global "^4.4.0" - "@storybook/client-logger@6.5.4": version "6.5.4" resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-6.5.4.tgz#57348015276e0453675968f6ca31d908ceb498ae" @@ -3223,21 +3127,6 @@ core-js "^3.8.2" global "^4.4.0" -"@storybook/components@6.5.3": - version "6.5.3" - resolved "https://registry.yarnpkg.com/@storybook/components/-/components-6.5.3.tgz#8d643d2d89c298e5e5c2957f7ffb171ba3288ecf" - integrity sha512-vYTsg9ADzkPeTsmN1bm351wGqq+oyb8SrAJzLe+FXN+dujIIA9sGEQb6eUZdGe121RDgTyFMO2zKurcJNnGnxQ== - dependencies: - "@storybook/client-logger" "6.5.3" - "@storybook/csf" "0.0.2--canary.4566f4d.1" - "@storybook/theming" "6.5.3" - "@types/react-syntax-highlighter" "11.0.5" - core-js "^3.8.2" - qs "^6.10.0" - react-syntax-highlighter "^15.4.5" - regenerator-runtime "^0.13.7" - util-deprecate "^1.0.2" - "@storybook/components@6.5.4": version "6.5.4" resolved "https://registry.yarnpkg.com/@storybook/components/-/components-6.5.4.tgz#8afdbba252ab957ba53318b34cb2593da964747b" @@ -3279,62 +3168,6 @@ unfetch "^4.2.0" util-deprecate "^1.0.2" -"@storybook/core-common@6.5.3": - version "6.5.3" - resolved "https://registry.yarnpkg.com/@storybook/core-common/-/core-common-6.5.3.tgz#5892e1ebc77f11b1058b716cb514bc2d1d5636ef" - integrity sha512-A0WJDm/Eo2eP8CZeAQPo8oep+Pbbm/uU6Gl/8GsvK7AVtDv/Sm/kyAWcvqMx5ovnZ7A+qYYjvHr90EZuDoltPg== - dependencies: - "@babel/core" "^7.12.10" - "@babel/plugin-proposal-class-properties" "^7.12.1" - "@babel/plugin-proposal-decorators" "^7.12.12" - "@babel/plugin-proposal-export-default-from" "^7.12.1" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.1" - "@babel/plugin-proposal-object-rest-spread" "^7.12.1" - "@babel/plugin-proposal-optional-chaining" "^7.12.7" - "@babel/plugin-proposal-private-methods" "^7.12.1" - "@babel/plugin-proposal-private-property-in-object" "^7.12.1" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-transform-arrow-functions" "^7.12.1" - "@babel/plugin-transform-block-scoping" "^7.12.12" - "@babel/plugin-transform-classes" "^7.12.1" - "@babel/plugin-transform-destructuring" "^7.12.1" - "@babel/plugin-transform-for-of" "^7.12.1" - "@babel/plugin-transform-parameters" "^7.12.1" - "@babel/plugin-transform-shorthand-properties" "^7.12.1" - "@babel/plugin-transform-spread" "^7.12.1" - "@babel/preset-env" "^7.12.11" - "@babel/preset-react" "^7.12.10" - "@babel/preset-typescript" "^7.12.7" - "@babel/register" "^7.12.1" - "@storybook/node-logger" "6.5.3" - "@storybook/semver" "^7.3.2" - "@types/node" "^14.0.10 || ^16.0.0" - "@types/pretty-hrtime" "^1.0.0" - babel-loader "^8.0.0" - babel-plugin-macros "^3.0.1" - babel-plugin-polyfill-corejs3 "^0.1.0" - chalk "^4.1.0" - core-js "^3.8.2" - express "^4.17.1" - file-system-cache "^1.0.5" - find-up "^5.0.0" - fork-ts-checker-webpack-plugin "^6.0.4" - fs-extra "^9.0.1" - glob "^7.1.6" - handlebars "^4.7.7" - interpret "^2.2.0" - json5 "^2.1.3" - lazy-universal-dotenv "^3.0.1" - picomatch "^2.3.0" - pkg-dir "^5.0.0" - pretty-hrtime "^1.0.3" - resolve-from "^5.0.0" - slash "^3.0.0" - telejson "^6.0.8" - ts-dedent "^2.0.0" - util-deprecate "^1.0.2" - webpack "4" - "@storybook/core-common@6.5.4": version "6.5.4" resolved "https://registry.yarnpkg.com/@storybook/core-common/-/core-common-6.5.4.tgz#e77f48a2c93b5eb656a3ad6dd0c01903ba7e57f3" @@ -3391,13 +3224,6 @@ util-deprecate "^1.0.2" webpack "4" -"@storybook/core-events@6.5.3": - version "6.5.3" - resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.5.3.tgz#57fb45187d6d60403149d9b16953989897e2bd6e" - integrity sha512-DTWFjXJIx+sZndv3lsJohVEJoUL5MgtkSeeKaypkJmZm9kXkylhA0NnA07CMRE6GMqCWw6NYGSe+qOEGsHj5ig== - dependencies: - core-js "^3.8.2" - "@storybook/core-events@6.5.4": version "6.5.4" resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.5.4.tgz#0c68ee42ac5afcc8ee7b56cd057d9a90d244067c" @@ -3600,17 +3426,6 @@ prettier ">=2.2.1 <=2.3.0" ts-dedent "^2.0.0" -"@storybook/node-logger@6.5.3": - version "6.5.3" - resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-6.5.3.tgz#6917bbbdaf2bb3b191bafadfe4f19c3ea3cbfa61" - integrity sha512-iG4uQJCtuT54p3zg0zJ7+ALPUrt7PTAXmXqN7ak/9YcWbnwtMlHgg8oTlCebwr+E3QPCMauJM2eLzC6F7bI76w== - dependencies: - "@types/npmlog" "^4.1.2" - chalk "^4.1.0" - core-js "^3.8.2" - npmlog "^5.0.1" - pretty-hrtime "^1.0.3" - "@storybook/node-logger@6.5.4", "@storybook/node-logger@^6.5.4": version "6.5.4" resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-6.5.4.tgz#1887abd364fd401ac7b76b313f92f12005a28c6f" @@ -3629,10 +3444,10 @@ dependencies: core-js "^3.8.2" -"@storybook/preset-create-react-app@^4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@storybook/preset-create-react-app/-/preset-create-react-app-4.1.0.tgz#8f2dc1d5ac07b806b7a3fa4f57654c21150a9821" - integrity sha512-xMQlWhT8qHBnfrep4g+f2UFndpAiYnhkilHaf081eA9hsnSlj7Z9WKgHC5n09jBhfZpgL5Zf7Mx3lNwhHoEXBw== +"@storybook/preset-create-react-app@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@storybook/preset-create-react-app/-/preset-create-react-app-4.1.1.tgz#4462bb1a355b81a3891c937bcc75d5ff7e60554c" + integrity sha512-zyiFkePMW4marb3YLYV1q8lBuIFUx0ZqY2e1HzPIzRclVrvTlUxYYi2FPTlr43OIInO4NSr4nTzHbVWKZZTjEA== dependencies: "@pmmmwh/react-refresh-webpack-plugin" "^0.5.1" "@storybook/react-docgen-typescript-plugin" canary @@ -3641,28 +3456,6 @@ pnp-webpack-plugin "^1.7.0" semver "^7.3.5" -"@storybook/preview-web@6.5.3": - version "6.5.3" - resolved "https://registry.yarnpkg.com/@storybook/preview-web/-/preview-web-6.5.3.tgz#f54fb17476c6a57d715ad2e46674b6b668e6729f" - integrity sha512-NI+sKFloj0vP1xAMaF1BhOAokB2u0qZ5rxx8lnU8eBmAukRURGoebuHWohBoQqniuupaNQK5hkUlJ3mkAPZi8Q== - dependencies: - "@storybook/addons" "6.5.3" - "@storybook/channel-postmessage" "6.5.3" - "@storybook/client-logger" "6.5.3" - "@storybook/core-events" "6.5.3" - "@storybook/csf" "0.0.2--canary.4566f4d.1" - "@storybook/store" "6.5.3" - ansi-to-html "^0.6.11" - core-js "^3.8.2" - global "^4.4.0" - lodash "^4.17.21" - qs "^6.10.0" - regenerator-runtime "^0.13.7" - synchronous-promise "^2.0.15" - ts-dedent "^2.0.0" - unfetch "^4.2.0" - util-deprecate "^1.0.2" - "@storybook/preview-web@6.5.4": version "6.5.4" resolved "https://registry.yarnpkg.com/@storybook/preview-web/-/preview-web-6.5.4.tgz#a6899add3be1937ea79c14c4861c0f038c71efaa" @@ -3739,15 +3532,6 @@ util-deprecate "^1.0.2" webpack ">=4.43.0 <6.0.0" -"@storybook/router@6.5.3": - version "6.5.3" - resolved "https://registry.yarnpkg.com/@storybook/router/-/router-6.5.3.tgz#55d8a0a5c3acdef9695482e38cd4d70f6926c261" - integrity sha512-UcErvdeuCTMYvmztDogrTK1DKQ8ZFkUR/46bEuVo4tg9OzlX3fr+JqD4RZHT4YOUYmDcTm6cLlUJhDalUpoU6Q== - dependencies: - "@storybook/client-logger" "6.5.3" - core-js "^3.8.2" - regenerator-runtime "^0.13.7" - "@storybook/router@6.5.4": version "6.5.4" resolved "https://registry.yarnpkg.com/@storybook/router/-/router-6.5.4.tgz#575f4ae36629086622a8b41626226ba4da025bb7" @@ -3781,27 +3565,6 @@ prettier ">=2.2.1 <=2.3.0" regenerator-runtime "^0.13.7" -"@storybook/store@6.5.3": - version "6.5.3" - resolved "https://registry.yarnpkg.com/@storybook/store/-/store-6.5.3.tgz#8bde9d3ad071c3612665b6190ed093784a98d22d" - integrity sha512-vI5w3OlDsCQE32C5AekRfHI6qX7s7iKRAUJKQE4Azqch37EAnMNLWE3E13KAzdLX1oU+JNRGHjJTogsQUR2UeQ== - dependencies: - "@storybook/addons" "6.5.3" - "@storybook/client-logger" "6.5.3" - "@storybook/core-events" "6.5.3" - "@storybook/csf" "0.0.2--canary.4566f4d.1" - core-js "^3.8.2" - fast-deep-equal "^3.1.3" - global "^4.4.0" - lodash "^4.17.21" - memoizerific "^1.11.3" - regenerator-runtime "^0.13.7" - slash "^3.0.0" - stable "^0.1.8" - synchronous-promise "^2.0.15" - ts-dedent "^2.0.0" - util-deprecate "^1.0.2" - "@storybook/store@6.5.4": version "6.5.4" resolved "https://registry.yarnpkg.com/@storybook/store/-/store-6.5.4.tgz#7770b7bffcc6c254a2497db2d4b1ee93b7a62659" @@ -3841,15 +3604,6 @@ read-pkg-up "^7.0.1" regenerator-runtime "^0.13.7" -"@storybook/theming@6.5.3": - version "6.5.3" - resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.5.3.tgz#a8df53df2812d49453a3410346123231e028c103" - integrity sha512-2tM46jahAhKRUzCcoaqPoqs+4imXqbze0dCPZ0cdVnfs14jhMB1lAfGE+diodCCaUcXUu8r2c5dTPKqqM1lHqQ== - dependencies: - "@storybook/client-logger" "6.5.3" - core-js "^3.8.2" - regenerator-runtime "^0.13.7" - "@storybook/theming@6.5.4": version "6.5.4" resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.5.4.tgz#3be001bf425f682f6e16ce3581e8cd109c85f8ea"