From 4ed5ce0d4786c062819fc4b6297e42d6d97955fd Mon Sep 17 00:00:00 2001 From: Vyacheslav Matyukhin Date: Tue, 20 Sep 2022 19:42:50 +0400 Subject: [PATCH] WIP --- ...leLibrary_FunctionRegistryLibrary_test.res | 7 + packages/squiggle-lang/scripts/lib.mjs | 2 +- packages/squiggle-lang/scripts/run.mjs | 4 +- .../squiggle-lang/src/rescript/FR/FR_Dict.res | 29 ++-- .../squiggle-lang/src/rescript/FR/FR_Dist.res | 12 +- .../squiggle-lang/src/rescript/FR/FR_Fn.res | 10 +- .../squiggle-lang/src/rescript/FR/FR_List.res | 10 +- .../src/rescript/FR/FR_Number.res | 5 +- .../src/rescript/FR/FR_Pointset.res | 49 +++--- .../src/rescript/FR/FR_Sampleset.res | 8 +- .../src/rescript/FR/FR_Scoring.res | 24 +-- .../FunctionRegistry_Core.res | 151 ++++-------------- .../FunctionRegistry_Helpers.res | 78 +++++---- 13 files changed, 156 insertions(+), 233 deletions(-) diff --git a/packages/squiggle-lang/__tests__/SquiggleLibrary/SquiggleLibrary_FunctionRegistryLibrary_test.res b/packages/squiggle-lang/__tests__/SquiggleLibrary/SquiggleLibrary_FunctionRegistryLibrary_test.res index 34a09172..fd1ec78e 100644 --- a/packages/squiggle-lang/__tests__/SquiggleLibrary/SquiggleLibrary_FunctionRegistryLibrary_test.res +++ b/packages/squiggle-lang/__tests__/SquiggleLibrary/SquiggleLibrary_FunctionRegistryLibrary_test.res @@ -80,6 +80,13 @@ describe("FunctionRegistry Library", () => { "SampleSet.toList(SampleSet.mapN([SampleSet.fromList([1,2,3,4,5,6]), SampleSet.fromList([6, 5, 4, 3, 2, 1])], {|x| x[0] > x[1] ? x[0] : x[1]}))", "Ok([6,5,4,4,5,6])", ) + + testEvalToBe("Dict.merge({a: 1, b: 2}, {b: 3, c: 4, d: 5})", "Ok({a: 1,b: 3,c: 4,d: 5})") + testEvalToBe("Dict.mergeMany([{a: 1, b: 2}, {c: 3, d: 4}, {c: 5, e: 6}])", "Ok({a: 1,b: 2,c: 5,d: 4,e: 6})") + testEvalToBe("Dict.keys({a: 1, b: 2})", "Ok(['a','b'])") + testEvalToBe("Dict.values({a: 1, b: 2})", "Ok([1,2])") + testEvalToBe("Dict.toList({a: 1, b: 2})", "Ok([['a',1],['b',2]])") + testEvalToBe("Dict.fromList([['a', 1], ['b', 2]])", "Ok({a: 1,b: 2})") }) describe("Fn auto-testing", () => { diff --git a/packages/squiggle-lang/scripts/lib.mjs b/packages/squiggle-lang/scripts/lib.mjs index ffa1d84f..6f778769 100644 --- a/packages/squiggle-lang/scripts/lib.mjs +++ b/packages/squiggle-lang/scripts/lib.mjs @@ -13,7 +13,7 @@ export const measure = (cb, times = 1) => { export const red = (str) => `\x1b[31m${str}\x1b[0m`; export const green = (str) => `\x1b[32m${str}\x1b[0m`; -export const run = (src, { output, sampleCount }) => { +export const run = (src, { output, sampleCount } = {}) => { const project = SqProject.create(); if (sampleCount) { project.setEnvironment({ diff --git a/packages/squiggle-lang/scripts/run.mjs b/packages/squiggle-lang/scripts/run.mjs index bc17314b..6dde265f 100755 --- a/packages/squiggle-lang/scripts/run.mjs +++ b/packages/squiggle-lang/scripts/run.mjs @@ -7,4 +7,6 @@ if (!src) { } console.log(`Running ${src}`); -run(src); +const sampleCount = process.env.SAMPLE_COUNT; + +run(src, { output: true, sampleCount }); diff --git a/packages/squiggle-lang/src/rescript/FR/FR_Dict.res b/packages/squiggle-lang/src/rescript/FR/FR_Dict.res index 2f36871c..f1f258ee 100644 --- a/packages/squiggle-lang/src/rescript/FR/FR_Dict.res +++ b/packages/squiggle-lang/src/rescript/FR/FR_Dict.res @@ -29,10 +29,6 @@ module Internals = { ->E.R2.fmap(Belt.Map.String.fromArray) ->E.R2.fmap(Wrappers.evRecord) - let merge = (a: t, b: t): Reducer_T.value => IEvRecord( - Belt.Map.String.merge(a, b, (_, _, c) => c), - ) - //Belt.Map.String has a function for mergeMany, but I couldn't understand how to use it yet. let mergeMany = (a: array): Reducer_T.value => { let mergedValues = @@ -54,8 +50,8 @@ let library = [ ~inputs=[FRTypeDict(FRTypeAny), FRTypeDict(FRTypeAny)], ~run=(inputs, _, _, _) => { switch inputs { - | [IEvRecord(d1), IEvRecord(d2)] => Internals.merge(d1, d2)->Ok - | _ => Error(impossibleError) + | [IEvRecord(d1), IEvRecord(d2)] => Internals.mergeMany([d1, d2])->Ok + | _ => impossibleError->Error } }, (), @@ -63,7 +59,7 @@ let library = [ ], (), ), - //TODO: Change to use new mergeMany() function. + Function.make( ~name="mergeMany", ~nameSpace, @@ -74,14 +70,17 @@ let library = [ FnDefinition.make( ~name="mergeMany", ~inputs=[FRTypeArray(FRTypeDict(FRTypeAny))], - ~run=(_, inputs, _, _) => - inputs - ->Prepare.ToTypedArray.dicts - ->E.R2.fmap(E.Dict.concatMany) - ->E.R2.fmap(Js.Dict.map((. r) => FunctionRegistry_Core.FRType.matchReverse(r))) - ->E.R2.fmap(r => r->Js.Dict.entries->Belt.Map.String.fromArray) - ->E.R2.fmap(Wrappers.evRecord) - ->E.R2.errMap(e => e->Reducer_ErrorValue.REOther), + ~run=(inputs, _, _, _) => { + switch inputs { + | [IEvArray(dicts)] => { + dicts->Belt.Array.map(dictValue => switch dictValue { + | IEvRecord(dict) => dict + | _ => impossibleError->Reducer_ErrorValue.toException + })->Internals.mergeMany->Ok + } + | _ => impossibleError->Error + } + }, (), ), ], diff --git a/packages/squiggle-lang/src/rescript/FR/FR_Dist.res b/packages/squiggle-lang/src/rescript/FR/FR_Dist.res index 1ee92c87..1ff4c3c5 100644 --- a/packages/squiggle-lang/src/rescript/FR/FR_Dist.res +++ b/packages/squiggle-lang/src/rescript/FR/FR_Dist.res @@ -22,7 +22,7 @@ module DistributionCreation = { FnDefinition.make( ~name, ~inputs=[FRTypeDistOrNumber, FRTypeDistOrNumber], - ~run=(_, inputs, env, _) => + ~run=(inputs, _, env, _) => inputs->Prepare.ToValueTuple.twoDistOrNumber->process(~fn, ~env), (), ) @@ -32,8 +32,8 @@ module DistributionCreation = { FnDefinition.make( ~name, ~inputs=[FRTypeRecord([("p5", FRTypeDistOrNumber), ("p95", FRTypeDistOrNumber)])], - ~run=(_, inputs, env, _) => - inputs->Prepare.ToValueTuple.Record.twoDistOrNumber->process(~fn, ~env), + ~run=(inputs, _, env, _) => + inputs->Prepare.ToValueTuple.Record.twoDistOrNumber(("p5", "p95"))->process(~fn, ~env), (), ) } @@ -42,8 +42,8 @@ module DistributionCreation = { FnDefinition.make( ~name, ~inputs=[FRTypeRecord([("mean", FRTypeDistOrNumber), ("stdev", FRTypeDistOrNumber)])], - ~run=(_, inputs, env, _) => - inputs->Prepare.ToValueTuple.Record.twoDistOrNumber->process(~fn, ~env), + ~run=(inputs, _, env, _) => + inputs->Prepare.ToValueTuple.Record.twoDistOrNumber(("mean", "stdev"))->process(~fn, ~env), (), ) } @@ -60,7 +60,7 @@ module DistributionCreation = { FnDefinition.make( ~name, ~inputs=[FRTypeDistOrNumber], - ~run=(_, inputs, env, _) => + ~run=(inputs, _, env, _) => inputs->Prepare.ToValueTuple.oneDistOrNumber->process(~fn, ~env), (), ) diff --git a/packages/squiggle-lang/src/rescript/FR/FR_Fn.res b/packages/squiggle-lang/src/rescript/FR/FR_Fn.res index 86db7edc..efd64bff 100644 --- a/packages/squiggle-lang/src/rescript/FR/FR_Fn.res +++ b/packages/squiggle-lang/src/rescript/FR/FR_Fn.res @@ -7,12 +7,12 @@ module Declaration = { ("inputs", FRTypeArray(FRTypeRecord([("min", FRTypeNumber), ("max", FRTypeNumber)]))), ]) - let fromExpressionValue = (e: frValue): result => { - switch FunctionRegistry_Helpers.Prepare.ToValueArray.Record.twoArgs([e]) { - | Ok([FRValueLambda(lambda), FRValueArray(inputs)]) => { + let fromExpressionValue = (e: Reducer_T.value): result => { + switch FunctionRegistry_Helpers.Prepare.ToValueArray.Record.twoArgs([e], ("fn", "inputs")) { + | Ok([IEvLambda(lambda), IEvArray(inputs)]) => { open FunctionRegistry_Helpers.Prepare let getMinMax = arg => - ToValueArray.Record.toArgs([arg]) + ToValueArray.Record.twoArgs([arg], ("min", "max")) ->E.R.bind(ToValueTuple.twoNumbers) ->E.R2.fmap(((min, max)) => Declaration.ContinuousFloatArg.make(min, max)) inputs @@ -49,7 +49,7 @@ let library = [ FnDefinition.make( ~name="declare", ~inputs=[Declaration.frType], - ~run=(_, inputs, _, _) => { + ~run=(inputs, _, _, _) => { inputs->getOrError(0)->E.R.bind(Declaration.fromExpressionValue)->E.R2.errMap(wrapError) }, (), diff --git a/packages/squiggle-lang/src/rescript/FR/FR_List.res b/packages/squiggle-lang/src/rescript/FR/FR_List.res index 081d453a..f4942b00 100644 --- a/packages/squiggle-lang/src/rescript/FR/FR_List.res +++ b/packages/squiggle-lang/src/rescript/FR/FR_List.res @@ -107,11 +107,11 @@ let library = [ FnDefinition.make( ~name="upTo", ~inputs=[FRTypeNumber, FRTypeNumber], - ~run=(_, inputs, _, _) => - inputs - ->Prepare.ToValueTuple.twoNumbers - ->E.R2.fmap(((low, high)) => Internals.upTo(low, high)) - ->E.R2.errMap(wrapError), + ~run=(inputs, _, _, _) => + switch inputs { + | [IEvNumber(low), IEvNumber(high)] => Internals.upTo(low, high)->Ok + | _ => impossibleError->Error + }, (), ), ], diff --git a/packages/squiggle-lang/src/rescript/FR/FR_Number.res b/packages/squiggle-lang/src/rescript/FR/FR_Number.res index 6e5426ac..91146ac5 100644 --- a/packages/squiggle-lang/src/rescript/FR/FR_Number.res +++ b/packages/squiggle-lang/src/rescript/FR/FR_Number.res @@ -9,8 +9,9 @@ module ArrayNumberDist = { FnDefinition.make( ~name, ~inputs=[FRTypeArray(FRTypeNumber)], - ~run=(_, inputs, _, _) => - Prepare.ToTypedArray.numbers(inputs) + ~run=(inputs, _, _, _) => + inputs + ->Prepare.ToTypedArray.numbers ->E.R.bind(r => E.A.length(r) === 0 ? Error("List is empty") : Ok(r)) ->E.R.bind(fn) ->E.R2.errMap(wrapError), diff --git a/packages/squiggle-lang/src/rescript/FR/FR_Pointset.res b/packages/squiggle-lang/src/rescript/FR/FR_Pointset.res index 54b8706d..dc428f0c 100644 --- a/packages/squiggle-lang/src/rescript/FR/FR_Pointset.res +++ b/packages/squiggle-lang/src/rescript/FR/FR_Pointset.res @@ -4,21 +4,28 @@ open FunctionRegistry_Helpers let nameSpace = "PointSet" let requiresNamespace = true -let inputsTodist = (inputs: array, makeDist) => { - let array = inputs->getOrError(0)->E.R.bind(Prepare.ToValueArray.Array.openA) - let xyCoords = - array->E.R.bind(xyCoords => - xyCoords - ->E.A2.fmap(xyCoord => - [xyCoord]->Prepare.ToValueArray.Record.twoArgs->E.R.bind(Prepare.ToValueTuple.twoNumbers) - ) - ->E.A.R.firstErrorOrOpen - ) - let expressionValue = - xyCoords - ->E.R.bind(r => r->XYShape.T.makeFromZipped->E.R2.errMap(XYShape.Error.toString)) - ->E.R2.fmap(r => Reducer_T.IEvDistribution(PointSet(makeDist(r)))) - expressionValue +let inputsToDist = (inputs: array, xyShapeToPointSetDist) => { + // TODO - rewritein more functional/functor-based style + switch inputs { + | [IEvArray(items)] => { + items->Belt.Array.map( + item => + switch item { + | IEvRecord(map) => { + let xValue = map->Belt.Map.String.getExn("x") + let yValue = map->Belt.Map.String.getExn("y") + switch (xValue, yValue) { + | (IEvNumber(x), IEvNumber(y)) => (x, y) + | _ => impossibleError->Reducer_ErrorValue.toException + } + } + | _ => impossibleError->Reducer_ErrorValue.toException + } + )->Ok->E.R.bind(r => r->XYShape.T.makeFromZipped->E.R2.errMap(XYShape.Error.toString)) + ->E.R2.fmap(r => Reducer_T.IEvDistribution(PointSet(r->xyShapeToPointSetDist))) + } + | _ => impossibleError->Reducer_ErrorValue.toException + } } module Internal = { @@ -53,9 +60,9 @@ let library = [ FnDefinition.make( ~name="fromDist", ~inputs=[FRTypeDist], - ~run=(_, inputs, env, _) => + ~run=(inputs, _, env, _) => switch inputs { - | [FRValueDist(dist)] => + | [IEvDistribution(dist)] => GenericDist.toPointSet( dist, ~xyPointLength=env.xyPointLength, @@ -110,8 +117,8 @@ let library = [ FnDefinition.make( ~name="makeContinuous", ~inputs=[FRTypeArray(FRTypeRecord([("x", FRTypeNumeric), ("y", FRTypeNumeric)]))], - ~run=(_, inputs, _, _) => - inputsTodist(inputs, r => Continuous(Continuous.make(r)))->E.R2.errMap(wrapError), + ~run=(inputs, _, _, _) => + inputsToDist(inputs, r => Continuous(Continuous.make(r)))->E.R2.errMap(wrapError), (), ), ], @@ -134,8 +141,8 @@ let library = [ FnDefinition.make( ~name="makeDiscrete", ~inputs=[FRTypeArray(FRTypeRecord([("x", FRTypeNumeric), ("y", FRTypeNumeric)]))], - ~run=(_, inputs, _, _) => - inputsTodist(inputs, r => Discrete(Discrete.make(r)))->E.R2.errMap(wrapError), + ~run=(inputs, _, _, _) => + inputsToDist(inputs, r => Discrete(Discrete.make(r)))->E.R2.errMap(wrapError), (), ), ], diff --git a/packages/squiggle-lang/src/rescript/FR/FR_Sampleset.res b/packages/squiggle-lang/src/rescript/FR/FR_Sampleset.res index 49f069ef..f21a6fde 100644 --- a/packages/squiggle-lang/src/rescript/FR/FR_Sampleset.res +++ b/packages/squiggle-lang/src/rescript/FR/FR_Sampleset.res @@ -89,9 +89,9 @@ let libaryBase = [ FnDefinition.make( ~name="fromDist", ~inputs=[FRTypeDist], - ~run=(_, inputs, environment, _) => + ~run=(inputs, _, environment, _) => switch inputs { - | [FRValueDist(dist)] => + | [IEvDistribution(dist)] => GenericDist.toSampleSetDist(dist, environment.sampleCount) ->E.R2.fmap(Wrappers.sampleSet) ->E.R2.fmap(Wrappers.evDistribution) @@ -113,9 +113,9 @@ let libaryBase = [ FnDefinition.make( ~name="fromList", ~inputs=[FRTypeArray(FRTypeNumber)], - ~run=(_, inputs, _, _) => { + ~run=(inputs, _, _, _) => { let sampleSet = - Prepare.ToTypedArray.numbers(inputs) |> E.R2.bind(r => + inputs->Prepare.ToTypedArray.numbers |> E.R2.bind(r => SampleSetDist.make(r)->E.R2.errMap(_ => "AM I HERE? WHYERE AMI??") ) sampleSet diff --git a/packages/squiggle-lang/src/rescript/FR/FR_Scoring.res b/packages/squiggle-lang/src/rescript/FR/FR_Scoring.res index 0f9b5811..450b9d63 100644 --- a/packages/squiggle-lang/src/rescript/FR/FR_Scoring.res +++ b/packages/squiggle-lang/src/rescript/FR/FR_Scoring.res @@ -30,14 +30,14 @@ let library = [ ("prior", FRTypeDist), ]), ], - ~run=(_, inputs, environment, _) => { - switch FunctionRegistry_Helpers.Prepare.ToValueArray.Record.threeArgs(inputs) { - | Ok([FRValueDist(estimate), FRValueDistOrNumber(FRValueDist(d)), FRValueDist(prior)]) => + ~run=(inputs, _, environment, _) => { + switch FunctionRegistry_Helpers.Prepare.ToValueArray.Record.threeArgs(inputs, ("estimate", "answer", "prior")) { + | Ok([IEvDistribution(estimate), IEvDistribution(d), IEvDistribution(prior)]) => runScoring(estimate, Score_Dist(d), Some(prior), environment) | Ok([ - FRValueDist(estimate), - FRValueDistOrNumber(FRValueNumber(d)), - FRValueDist(prior), + IEvDistribution(estimate), + IEvNumber(d), + IEvDistribution(prior), ]) => runScoring(estimate, Score_Scalar(d), Some(prior), environment) | Error(e) => Error(e->FunctionRegistry_Helpers.wrapError) @@ -49,11 +49,11 @@ let library = [ FnDefinition.make( ~name="logScore", ~inputs=[FRTypeRecord([("estimate", FRTypeDist), ("answer", FRTypeDistOrNumber)])], - ~run=(_, inputs, environment, _) => { - switch FunctionRegistry_Helpers.Prepare.ToValueArray.Record.twoArgs(inputs) { - | Ok([FRValueDist(estimate), FRValueDistOrNumber(FRValueDist(d))]) => + ~run=(inputs, _, environment, _) => { + switch FunctionRegistry_Helpers.Prepare.ToValueArray.Record.twoArgs(inputs, ("estimate", "answer")) { + | Ok([IEvDistribution(estimate), IEvDistribution(d)]) => runScoring(estimate, Score_Dist(d), None, environment) - | Ok([FRValueDist(estimate), FRValueDistOrNumber(FRValueNumber(d))]) => + | Ok([IEvDistribution(estimate), IEvNumber(d)]) => runScoring(estimate, Score_Scalar(d), None, environment) | Error(e) => Error(e->FunctionRegistry_Helpers.wrapError) | _ => Error(FunctionRegistry_Helpers.impossibleError) @@ -74,9 +74,9 @@ let library = [ FnDefinition.make( ~name="klDivergence", ~inputs=[FRTypeDist, FRTypeDist], - ~run=(_, inputs, environment, _) => { + ~run=(inputs, _, environment, _) => { switch inputs { - | [FRValueDist(estimate), FRValueDist(d)] => + | [IEvDistribution(estimate), IEvDistribution(d)] => runScoring(estimate, Score_Dist(d), None, environment) | _ => Error(FunctionRegistry_Helpers.impossibleError) } diff --git a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Core.res b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Core.res index 4ae50fa3..128d0b8e 100644 --- a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Core.res +++ b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Core.res @@ -23,35 +23,14 @@ type rec 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) - | FRValueBool(bool) - | FRValueDate(Js.Date.t) - | FRValueTimeDuration(float) - | FRValueDist(DistributionTypes.genericDist) - | FRValueArray(array) - | FRValueDistOrNumber(frValueDistOrNumber) - | FRValueRecord(frValueRecord) - | FRValueLambda(Reducer_T.lambdaValue) - | FRValueString(string) - | FRValueVariant(string) - | FRValueAny(frValue) - | FRValueDict(Js.Dict.t) -and frValueRecord = array -and frValueRecordParam = (string, frValue) -and frValueDictParam = (string, frValue) -and frValueDistOrNumber = FRValueNumber(float) | FRValueDist(DistributionTypes.genericDist) +type frValueDistOrNumber = FRValueNumber(float) | FRValueDist(DistributionTypes.genericDist) type fnDefinition = { name: string, inputs: array, run: ( array, - array, + unit, Reducer_T.environment, Reducer_T.reducerFn, ) => result, @@ -91,104 +70,43 @@ module FRType = { | FRTypeAny => `any` } - let rec toFrValue = (r: Reducer_T.value): option => - // not all value variants are supported, but it's not important (we'll probably deprecate frValues soon anyway) - switch r { - | IEvNumber(f) => Some(FRValueNumber(f)) - | IEvString(f) => Some(FRValueString(f)) - | IEvDistribution(f) => Some(FRValueDistOrNumber(FRValueDist(f))) - | IEvLambda(f) => Some(FRValueLambda(f)) - | IEvArray(elements) => - elements->E.A2.fmap(toFrValue)->E.A.O.openIfAllSome->E.O2.fmap(r => FRValueArray(r)) - | IEvRecord(map) => - Belt.Map.String.toArray(map) - ->E.A2.fmap(((key, item)) => item->toFrValue->E.O2.fmap(o => (key, o))) - ->E.A.O.openIfAllSome - ->E.O2.fmap(r => FRValueRecord(r)) - | _ => None - } - - let rec matchWithExpressionValue = (t: t, r: Reducer_T.value): option => + let rec matchWithValue = (t: t, r: Reducer_T.value): bool => switch (t, r) { - | (FRTypeAny, f) => toFrValue(f) - | (FRTypeString, IEvString(f)) => Some(FRValueString(f)) - | (FRTypeNumber, IEvNumber(f)) => Some(FRValueNumber(f)) - | (FRTypeBool, IEvBool(f)) => Some(FRValueBool(f)) - | (FRTypeDate, IEvDate(f)) => Some(FRValueDate(f)) - | (FRTypeTimeDuration, IEvTimeDuration(f)) => Some(FRValueTimeDuration(f)) - | (FRTypeDistOrNumber, IEvNumber(f)) => Some(FRValueDistOrNumber(FRValueNumber(f))) - | (FRTypeDistOrNumber, IEvDistribution(Symbolic(#Float(f)))) => - Some(FRValueDistOrNumber(FRValueNumber(f))) - | (FRTypeDistOrNumber, IEvDistribution(f)) => Some(FRValueDistOrNumber(FRValueDist(f))) - | (FRTypeDist, IEvDistribution(f)) => Some(FRValueDist(f)) - | (FRTypeNumeric, IEvNumber(f)) => Some(FRValueNumber(f)) - | (FRTypeNumeric, IEvDistribution(Symbolic(#Float(f)))) => Some(FRValueNumber(f)) - | (FRTypeLambda, IEvLambda(f)) => Some(FRValueLambda(f)) + | (FRTypeAny, _) => true + | (FRTypeString, IEvString(_)) => true + | (FRTypeNumber, IEvNumber(_)) => true + | (FRTypeBool, IEvBool(_)) => true + | (FRTypeDate, IEvDate(_)) => true + | (FRTypeTimeDuration, IEvTimeDuration(_)) => true + | (FRTypeDistOrNumber, IEvNumber(_)) => true + | (FRTypeDistOrNumber, IEvDistribution(_)) => true + | (FRTypeDist, IEvDistribution(_)) => true + | (FRTypeNumeric, IEvNumber(_)) => true + | (FRTypeNumeric, IEvDistribution(Symbolic(#Float(_)))) => true + | (FRTypeLambda, IEvLambda(_)) => true | (FRTypeArray(intendedType), IEvArray(elements)) => { - let el = elements->E.A2.fmap(matchWithExpressionValue(intendedType)) - E.A.O.openIfAllSome(el)->E.O2.fmap(r => FRValueArray(r)) + elements->Belt.Array.every(v => matchWithValue(intendedType, v)) } | (FRTypeDict(r), IEvRecord(map)) => - map - ->Belt.Map.String.toArray - ->E.A2.fmap(((key, item)) => matchWithExpressionValue(r, item)->E.O2.fmap(o => (key, o))) - ->E.A.O.openIfAllSome - ->E.O2.fmap(r => FRValueDict(Js.Dict.fromArray(r))) + map->Belt.Map.String.valuesToArray->Belt.Array.every(v => matchWithValue(r, v)) | (FRTypeRecord(recordParams), IEvRecord(map)) => { - let getAndMatch = (name, input) => - Belt.Map.String.get(map, 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 + recordParams->Belt.Array.every(((name, input)) => { + switch map->Belt.Map.String.get(name) { + | Some(v) => matchWithValue(input, v) + | None => false + } + }) + } + | _ => false } - let rec matchReverse = (e: frValue): Reducer_T.value => - switch e { - | FRValueNumber(f) => IEvNumber(f) - | FRValueBool(f) => IEvBool(f) - | FRValueDate(f) => IEvDate(f) - | FRValueTimeDuration(f) => IEvTimeDuration(f) - | FRValueDistOrNumber(FRValueNumber(n)) => IEvNumber(n) - | FRValueDistOrNumber(FRValueDist(n)) => IEvDistribution(n) - | FRValueDist(dist) => IEvDistribution(dist) - | FRValueArray(elements) => IEvArray(elements->E.A2.fmap(matchReverse)) - | FRValueRecord(frValueRecord) => { - let map = - frValueRecord - ->E.A2.fmap(((name, value)) => (name, matchReverse(value))) - ->Belt.Map.String.fromArray - IEvRecord(map) - } - | FRValueDict(frValueRecord) => { - let map = - frValueRecord - ->Js.Dict.entries - ->E.A2.fmap(((name, value)) => (name, matchReverse(value))) - ->Belt.Map.String.fromArray - IEvRecord(map) - } - | FRValueLambda(l) => IEvLambda(l) - | FRValueString(string) => IEvString(string) - | FRValueVariant(string) => IEvString(string) - | FRValueAny(f) => matchReverse(f) - } - - let matchWithExpressionValueArray = (inputs: array, args: array): option< - array, - > => { + let matchWithValueArray = (inputs: array, args: array): bool => { let isSameLength = E.A.length(inputs) == E.A.length(args) if !isSameLength { - None + false } else { E.A.zip(inputs, args) - ->E.A2.fmap(((input, arg)) => matchWithExpressionValue(input, arg)) - ->E.A.O.openIfAllSome + ->Belt.Array.every(((input, arg)) => matchWithValue(input, arg)) } } } @@ -202,11 +120,7 @@ module FnDefinition = { } let isMatch = (t: t, args: array) => { - let argValues = FRType.matchWithExpressionValueArray(t.inputs, args) - switch argValues { - | Some(_) => true - | None => false - } + FRType.matchWithValueArray(t.inputs, args) } let run = ( @@ -215,10 +129,9 @@ module FnDefinition = { env: Reducer_T.environment, reducer: Reducer_T.reducerFn, ) => { - let argValues = FRType.matchWithExpressionValueArray(t.inputs, args) - switch argValues { - | Some(values) => t.run(args, values, env, reducer) - | None => REOther("Incorrect Types")->Error + switch t->isMatch(args) { + | true => t.run(args, (), env, reducer) + | false => REOther("Incorrect Types")->Error } } diff --git a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Helpers.res b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Helpers.res index 3edbe5da..3b1bd7d7 100644 --- a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Helpers.res +++ b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Helpers.res @@ -21,27 +21,30 @@ module Wrappers = { let getOrError = (a, g) => E.A.get(a, g) |> E.O.toResult(impossibleErrorString) module Prepare = { - type t = frValue - type ts = array + type t = value + type ts = array type err = string module ToValueArray = { module Record = { - let twoArgs = (inputs: ts): result => + let twoArgs = (inputs: ts, (arg1: string, arg2: string)): result => switch inputs { - | [FRValueRecord([(_, n1), (_, n2)])] => Ok([n1, n2]) + | [IEvRecord(map)] => { + let n1 = map->Belt.Map.String.getExn(arg1) + let n2 = map->Belt.Map.String.getExn(arg2) + Ok([n1, n2]) + } | _ => Error(impossibleErrorString) } - let threeArgs = (inputs: ts): result => + let threeArgs = (inputs: ts, (arg1: string, arg2: string, arg3: string)): result => switch inputs { - | [FRValueRecord([(_, n1), (_, n2), (_, n3)])] => Ok([n1, n2, n3]) - | _ => Error(impossibleErrorString) + | [IEvRecord(map)] => { + let n1 = map->Belt.Map.String.getExn(arg1) + let n2 = map->Belt.Map.String.getExn(arg2) + let n3 = map->Belt.Map.String.getExn(arg3) + Ok([n1, n2, n3]) } - - let toArgs = (inputs: ts): result => - switch inputs { - | [FRValueRecord(args)] => args->E.A2.fmap(((_, b)) => b)->Ok | _ => Error(impossibleErrorString) } } @@ -49,13 +52,13 @@ module Prepare = { module Array = { let openA = (inputs: t): result => switch inputs { - | FRValueArray(n) => Ok(n) + | IEvArray(n) => Ok(n) | _ => Error(impossibleErrorString) } let arrayOfArrays = (inputs: t): result, err> => switch inputs { - | FRValueArray(n) => n->E.A2.fmap(openA)->E.A.R.firstErrorOrOpen + | IEvArray(n) => n->E.A2.fmap(openA)->E.A.R.firstErrorOrOpen | _ => Error(impossibleErrorString) } } @@ -64,7 +67,10 @@ module Prepare = { module ToValueTuple = { let twoDistOrNumber = (values: ts): result<(frValueDistOrNumber, frValueDistOrNumber), err> => { switch values { - | [FRValueDistOrNumber(a1), FRValueDistOrNumber(a2)] => Ok(a1, a2) + | [IEvDistribution(a1), IEvDistribution(a2)] => Ok(FRValueDist(a1), FRValueDist(a2)) + | [IEvDistribution(a1), IEvNumber(a2)] => Ok(FRValueDist(a1), FRValueNumber(a2)) + | [IEvNumber(a1), IEvDistribution(a2)] => Ok(FRValueNumber(a1), FRValueDist(a2)) + | [IEvNumber(a1), IEvNumber(a2)] => Ok(FRValueNumber(a1), FRValueNumber(a2)) | _ => Error(impossibleErrorString) } } @@ -74,66 +80,54 @@ module Prepare = { err, > => { switch values { - | [FRValueDist(a1), FRValueDist(a2)] => Ok(a1, a2) + | [IEvDistribution(a1), IEvDistribution(a2)] => Ok(a1, a2) | _ => Error(impossibleErrorString) } } let twoNumbers = (values: ts): result<(float, float), err> => { switch values { - | [FRValueNumber(a1), FRValueNumber(a2)] => Ok(a1, a2) + | [IEvNumber(a1), IEvNumber(a2)] => Ok(a1, a2) | _ => Error(impossibleErrorString) } } let threeNumbers = (values: ts): result<(float, float, float), err> => { switch values { - | [FRValueNumber(a1), FRValueNumber(a2), FRValueNumber(a3)] => Ok(a1, a2, a3) + | [IEvNumber(a1), IEvNumber(a2), IEvNumber(a3)] => Ok(a1, a2, a3) | _ => Error(impossibleErrorString) } } let oneDistOrNumber = (values: ts): result => { switch values { - | [FRValueDistOrNumber(a1)] => Ok(a1) + | [IEvNumber(a1)] => FRValueNumber(a1)->Ok + | [IEvDistribution(a2)] => FRValueDist(a2)->Ok | _ => Error(impossibleErrorString) } } module Record = { - let twoDistOrNumber = (values: ts): result<(frValueDistOrNumber, frValueDistOrNumber), err> => - values->ToValueArray.Record.twoArgs->E.R.bind(twoDistOrNumber) + let twoDistOrNumber = (values: ts, labels: (string, string)): result<(frValueDistOrNumber, frValueDistOrNumber), err> => + values->ToValueArray.Record.twoArgs(labels)->E.R.bind(twoDistOrNumber) - let twoDist = (values: ts): result< + let twoDist = (values: ts, labels: (string, string)): result< (DistributionTypes.genericDist, DistributionTypes.genericDist), err, - > => values->ToValueArray.Record.twoArgs->E.R.bind(twoDist) + > => values->ToValueArray.Record.twoArgs(labels)->E.R.bind(twoDist) } } - module ToArrayRecordPairs = { - let twoArgs = (input: t): result, err> => { - let array = input->ToValueArray.Array.openA - let pairs = - array->E.R.bind(pairs => - pairs - ->E.A2.fmap(xyCoord => [xyCoord]->ToValueArray.Record.twoArgs) - ->E.A.R.firstErrorOrOpen - ) - pairs - } - } - - let oneNumber = (values: t): result => { - switch values { - | FRValueNumber(a1) => Ok(a1) + let oneNumber = (value: t): result => { + switch value { + | IEvNumber(a1) => Ok(a1) | _ => Error(impossibleErrorString) } } - let oneDict = (values: t): result, err> => { - switch values { - | FRValueDict(a1) => Ok(a1) + let oneDict = (value: t): result => { + switch value { + | IEvRecord(a1) => Ok(a1) | _ => Error(impossibleErrorString) } } @@ -145,7 +139,7 @@ module Prepare = { inputs->getOrError(0)->E.R.bind(ToValueArray.Array.openA)->E.R.bind(openNumbers) } - let dicts = (inputs: ts): Belt.Result.t>, err> => { + let dicts = (inputs: ts): Belt.Result.t, err> => { let openDicts = (elements: array) => elements->E.A2.fmap(oneDict)->E.A.R.firstErrorOrOpen inputs->getOrError(0)->E.R.bind(ToValueArray.Array.openA)->E.R.bind(openDicts) }