This commit is contained in:
Vyacheslav Matyukhin 2022-09-20 19:42:50 +04:00
parent cdc49b378a
commit 4ed5ce0d47
No known key found for this signature in database
GPG Key ID: 3D2A774C5489F96C
13 changed files with 156 additions and 233 deletions

View File

@ -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]}))", "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])", "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", () => { describe("Fn auto-testing", () => {

View File

@ -13,7 +13,7 @@ export const measure = (cb, times = 1) => {
export const red = (str) => `\x1b[31m${str}\x1b[0m`; export const red = (str) => `\x1b[31m${str}\x1b[0m`;
export const green = (str) => `\x1b[32m${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(); const project = SqProject.create();
if (sampleCount) { if (sampleCount) {
project.setEnvironment({ project.setEnvironment({

View File

@ -7,4 +7,6 @@ if (!src) {
} }
console.log(`Running ${src}`); console.log(`Running ${src}`);
run(src); const sampleCount = process.env.SAMPLE_COUNT;
run(src, { output: true, sampleCount });

View File

@ -29,10 +29,6 @@ module Internals = {
->E.R2.fmap(Belt.Map.String.fromArray) ->E.R2.fmap(Belt.Map.String.fromArray)
->E.R2.fmap(Wrappers.evRecord) ->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. //Belt.Map.String has a function for mergeMany, but I couldn't understand how to use it yet.
let mergeMany = (a: array<t>): Reducer_T.value => { let mergeMany = (a: array<t>): Reducer_T.value => {
let mergedValues = let mergedValues =
@ -54,8 +50,8 @@ let library = [
~inputs=[FRTypeDict(FRTypeAny), FRTypeDict(FRTypeAny)], ~inputs=[FRTypeDict(FRTypeAny), FRTypeDict(FRTypeAny)],
~run=(inputs, _, _, _) => { ~run=(inputs, _, _, _) => {
switch inputs { switch inputs {
| [IEvRecord(d1), IEvRecord(d2)] => Internals.merge(d1, d2)->Ok | [IEvRecord(d1), IEvRecord(d2)] => Internals.mergeMany([d1, d2])->Ok
| _ => Error(impossibleError) | _ => impossibleError->Error
} }
}, },
(), (),
@ -63,7 +59,7 @@ let library = [
], ],
(), (),
), ),
//TODO: Change to use new mergeMany() function.
Function.make( Function.make(
~name="mergeMany", ~name="mergeMany",
~nameSpace, ~nameSpace,
@ -74,14 +70,17 @@ let library = [
FnDefinition.make( FnDefinition.make(
~name="mergeMany", ~name="mergeMany",
~inputs=[FRTypeArray(FRTypeDict(FRTypeAny))], ~inputs=[FRTypeArray(FRTypeDict(FRTypeAny))],
~run=(_, inputs, _, _) => ~run=(inputs, _, _, _) => {
inputs switch inputs {
->Prepare.ToTypedArray.dicts | [IEvArray(dicts)] => {
->E.R2.fmap(E.Dict.concatMany) dicts->Belt.Array.map(dictValue => switch dictValue {
->E.R2.fmap(Js.Dict.map((. r) => FunctionRegistry_Core.FRType.matchReverse(r))) | IEvRecord(dict) => dict
->E.R2.fmap(r => r->Js.Dict.entries->Belt.Map.String.fromArray) | _ => impossibleError->Reducer_ErrorValue.toException
->E.R2.fmap(Wrappers.evRecord) })->Internals.mergeMany->Ok
->E.R2.errMap(e => e->Reducer_ErrorValue.REOther), }
| _ => impossibleError->Error
}
},
(), (),
), ),
], ],

View File

@ -22,7 +22,7 @@ module DistributionCreation = {
FnDefinition.make( FnDefinition.make(
~name, ~name,
~inputs=[FRTypeDistOrNumber, FRTypeDistOrNumber], ~inputs=[FRTypeDistOrNumber, FRTypeDistOrNumber],
~run=(_, inputs, env, _) => ~run=(inputs, _, env, _) =>
inputs->Prepare.ToValueTuple.twoDistOrNumber->process(~fn, ~env), inputs->Prepare.ToValueTuple.twoDistOrNumber->process(~fn, ~env),
(), (),
) )
@ -32,8 +32,8 @@ module DistributionCreation = {
FnDefinition.make( FnDefinition.make(
~name, ~name,
~inputs=[FRTypeRecord([("p5", FRTypeDistOrNumber), ("p95", FRTypeDistOrNumber)])], ~inputs=[FRTypeRecord([("p5", FRTypeDistOrNumber), ("p95", FRTypeDistOrNumber)])],
~run=(_, inputs, env, _) => ~run=(inputs, _, env, _) =>
inputs->Prepare.ToValueTuple.Record.twoDistOrNumber->process(~fn, ~env), inputs->Prepare.ToValueTuple.Record.twoDistOrNumber(("p5", "p95"))->process(~fn, ~env),
(), (),
) )
} }
@ -42,8 +42,8 @@ module DistributionCreation = {
FnDefinition.make( FnDefinition.make(
~name, ~name,
~inputs=[FRTypeRecord([("mean", FRTypeDistOrNumber), ("stdev", FRTypeDistOrNumber)])], ~inputs=[FRTypeRecord([("mean", FRTypeDistOrNumber), ("stdev", FRTypeDistOrNumber)])],
~run=(_, inputs, env, _) => ~run=(inputs, _, env, _) =>
inputs->Prepare.ToValueTuple.Record.twoDistOrNumber->process(~fn, ~env), inputs->Prepare.ToValueTuple.Record.twoDistOrNumber(("mean", "stdev"))->process(~fn, ~env),
(), (),
) )
} }
@ -60,7 +60,7 @@ module DistributionCreation = {
FnDefinition.make( FnDefinition.make(
~name, ~name,
~inputs=[FRTypeDistOrNumber], ~inputs=[FRTypeDistOrNumber],
~run=(_, inputs, env, _) => ~run=(inputs, _, env, _) =>
inputs->Prepare.ToValueTuple.oneDistOrNumber->process(~fn, ~env), inputs->Prepare.ToValueTuple.oneDistOrNumber->process(~fn, ~env),
(), (),
) )

View File

@ -7,12 +7,12 @@ module Declaration = {
("inputs", FRTypeArray(FRTypeRecord([("min", FRTypeNumber), ("max", FRTypeNumber)]))), ("inputs", FRTypeArray(FRTypeRecord([("min", FRTypeNumber), ("max", FRTypeNumber)]))),
]) ])
let fromExpressionValue = (e: frValue): result<Reducer_T.value, string> => { let fromExpressionValue = (e: Reducer_T.value): result<Reducer_T.value, string> => {
switch FunctionRegistry_Helpers.Prepare.ToValueArray.Record.twoArgs([e]) { switch FunctionRegistry_Helpers.Prepare.ToValueArray.Record.twoArgs([e], ("fn", "inputs")) {
| Ok([FRValueLambda(lambda), FRValueArray(inputs)]) => { | Ok([IEvLambda(lambda), IEvArray(inputs)]) => {
open FunctionRegistry_Helpers.Prepare open FunctionRegistry_Helpers.Prepare
let getMinMax = arg => let getMinMax = arg =>
ToValueArray.Record.toArgs([arg]) ToValueArray.Record.twoArgs([arg], ("min", "max"))
->E.R.bind(ToValueTuple.twoNumbers) ->E.R.bind(ToValueTuple.twoNumbers)
->E.R2.fmap(((min, max)) => Declaration.ContinuousFloatArg.make(min, max)) ->E.R2.fmap(((min, max)) => Declaration.ContinuousFloatArg.make(min, max))
inputs inputs
@ -49,7 +49,7 @@ let library = [
FnDefinition.make( FnDefinition.make(
~name="declare", ~name="declare",
~inputs=[Declaration.frType], ~inputs=[Declaration.frType],
~run=(_, inputs, _, _) => { ~run=(inputs, _, _, _) => {
inputs->getOrError(0)->E.R.bind(Declaration.fromExpressionValue)->E.R2.errMap(wrapError) inputs->getOrError(0)->E.R.bind(Declaration.fromExpressionValue)->E.R2.errMap(wrapError)
}, },
(), (),

View File

@ -107,11 +107,11 @@ let library = [
FnDefinition.make( FnDefinition.make(
~name="upTo", ~name="upTo",
~inputs=[FRTypeNumber, FRTypeNumber], ~inputs=[FRTypeNumber, FRTypeNumber],
~run=(_, inputs, _, _) => ~run=(inputs, _, _, _) =>
inputs switch inputs {
->Prepare.ToValueTuple.twoNumbers | [IEvNumber(low), IEvNumber(high)] => Internals.upTo(low, high)->Ok
->E.R2.fmap(((low, high)) => Internals.upTo(low, high)) | _ => impossibleError->Error
->E.R2.errMap(wrapError), },
(), (),
), ),
], ],

View File

@ -9,8 +9,9 @@ module ArrayNumberDist = {
FnDefinition.make( FnDefinition.make(
~name, ~name,
~inputs=[FRTypeArray(FRTypeNumber)], ~inputs=[FRTypeArray(FRTypeNumber)],
~run=(_, inputs, _, _) => ~run=(inputs, _, _, _) =>
Prepare.ToTypedArray.numbers(inputs) inputs
->Prepare.ToTypedArray.numbers
->E.R.bind(r => E.A.length(r) === 0 ? Error("List is empty") : Ok(r)) ->E.R.bind(r => E.A.length(r) === 0 ? Error("List is empty") : Ok(r))
->E.R.bind(fn) ->E.R.bind(fn)
->E.R2.errMap(wrapError), ->E.R2.errMap(wrapError),

View File

@ -4,21 +4,28 @@ open FunctionRegistry_Helpers
let nameSpace = "PointSet" let nameSpace = "PointSet"
let requiresNamespace = true let requiresNamespace = true
let inputsTodist = (inputs: array<FunctionRegistry_Core.frValue>, makeDist) => { let inputsToDist = (inputs: array<Reducer_T.value>, xyShapeToPointSetDist) => {
let array = inputs->getOrError(0)->E.R.bind(Prepare.ToValueArray.Array.openA) // TODO - rewritein more functional/functor-based style
let xyCoords = switch inputs {
array->E.R.bind(xyCoords => | [IEvArray(items)] => {
xyCoords items->Belt.Array.map(
->E.A2.fmap(xyCoord => item =>
[xyCoord]->Prepare.ToValueArray.Record.twoArgs->E.R.bind(Prepare.ToValueTuple.twoNumbers) switch item {
) | IEvRecord(map) => {
->E.A.R.firstErrorOrOpen let xValue = map->Belt.Map.String.getExn("x")
) let yValue = map->Belt.Map.String.getExn("y")
let expressionValue = switch (xValue, yValue) {
xyCoords | (IEvNumber(x), IEvNumber(y)) => (x, y)
->E.R.bind(r => r->XYShape.T.makeFromZipped->E.R2.errMap(XYShape.Error.toString)) | _ => impossibleError->Reducer_ErrorValue.toException
->E.R2.fmap(r => Reducer_T.IEvDistribution(PointSet(makeDist(r)))) }
expressionValue }
| _ => 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 = { module Internal = {
@ -53,9 +60,9 @@ let library = [
FnDefinition.make( FnDefinition.make(
~name="fromDist", ~name="fromDist",
~inputs=[FRTypeDist], ~inputs=[FRTypeDist],
~run=(_, inputs, env, _) => ~run=(inputs, _, env, _) =>
switch inputs { switch inputs {
| [FRValueDist(dist)] => | [IEvDistribution(dist)] =>
GenericDist.toPointSet( GenericDist.toPointSet(
dist, dist,
~xyPointLength=env.xyPointLength, ~xyPointLength=env.xyPointLength,
@ -110,8 +117,8 @@ let library = [
FnDefinition.make( FnDefinition.make(
~name="makeContinuous", ~name="makeContinuous",
~inputs=[FRTypeArray(FRTypeRecord([("x", FRTypeNumeric), ("y", FRTypeNumeric)]))], ~inputs=[FRTypeArray(FRTypeRecord([("x", FRTypeNumeric), ("y", FRTypeNumeric)]))],
~run=(_, inputs, _, _) => ~run=(inputs, _, _, _) =>
inputsTodist(inputs, r => Continuous(Continuous.make(r)))->E.R2.errMap(wrapError), inputsToDist(inputs, r => Continuous(Continuous.make(r)))->E.R2.errMap(wrapError),
(), (),
), ),
], ],
@ -134,8 +141,8 @@ let library = [
FnDefinition.make( FnDefinition.make(
~name="makeDiscrete", ~name="makeDiscrete",
~inputs=[FRTypeArray(FRTypeRecord([("x", FRTypeNumeric), ("y", FRTypeNumeric)]))], ~inputs=[FRTypeArray(FRTypeRecord([("x", FRTypeNumeric), ("y", FRTypeNumeric)]))],
~run=(_, inputs, _, _) => ~run=(inputs, _, _, _) =>
inputsTodist(inputs, r => Discrete(Discrete.make(r)))->E.R2.errMap(wrapError), inputsToDist(inputs, r => Discrete(Discrete.make(r)))->E.R2.errMap(wrapError),
(), (),
), ),
], ],

View File

@ -89,9 +89,9 @@ let libaryBase = [
FnDefinition.make( FnDefinition.make(
~name="fromDist", ~name="fromDist",
~inputs=[FRTypeDist], ~inputs=[FRTypeDist],
~run=(_, inputs, environment, _) => ~run=(inputs, _, environment, _) =>
switch inputs { switch inputs {
| [FRValueDist(dist)] => | [IEvDistribution(dist)] =>
GenericDist.toSampleSetDist(dist, environment.sampleCount) GenericDist.toSampleSetDist(dist, environment.sampleCount)
->E.R2.fmap(Wrappers.sampleSet) ->E.R2.fmap(Wrappers.sampleSet)
->E.R2.fmap(Wrappers.evDistribution) ->E.R2.fmap(Wrappers.evDistribution)
@ -113,9 +113,9 @@ let libaryBase = [
FnDefinition.make( FnDefinition.make(
~name="fromList", ~name="fromList",
~inputs=[FRTypeArray(FRTypeNumber)], ~inputs=[FRTypeArray(FRTypeNumber)],
~run=(_, inputs, _, _) => { ~run=(inputs, _, _, _) => {
let sampleSet = 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??") SampleSetDist.make(r)->E.R2.errMap(_ => "AM I HERE? WHYERE AMI??")
) )
sampleSet sampleSet

View File

@ -30,14 +30,14 @@ let library = [
("prior", FRTypeDist), ("prior", FRTypeDist),
]), ]),
], ],
~run=(_, inputs, environment, _) => { ~run=(inputs, _, environment, _) => {
switch FunctionRegistry_Helpers.Prepare.ToValueArray.Record.threeArgs(inputs) { switch FunctionRegistry_Helpers.Prepare.ToValueArray.Record.threeArgs(inputs, ("estimate", "answer", "prior")) {
| Ok([FRValueDist(estimate), FRValueDistOrNumber(FRValueDist(d)), FRValueDist(prior)]) => | Ok([IEvDistribution(estimate), IEvDistribution(d), IEvDistribution(prior)]) =>
runScoring(estimate, Score_Dist(d), Some(prior), environment) runScoring(estimate, Score_Dist(d), Some(prior), environment)
| Ok([ | Ok([
FRValueDist(estimate), IEvDistribution(estimate),
FRValueDistOrNumber(FRValueNumber(d)), IEvNumber(d),
FRValueDist(prior), IEvDistribution(prior),
]) => ]) =>
runScoring(estimate, Score_Scalar(d), Some(prior), environment) runScoring(estimate, Score_Scalar(d), Some(prior), environment)
| Error(e) => Error(e->FunctionRegistry_Helpers.wrapError) | Error(e) => Error(e->FunctionRegistry_Helpers.wrapError)
@ -49,11 +49,11 @@ let library = [
FnDefinition.make( FnDefinition.make(
~name="logScore", ~name="logScore",
~inputs=[FRTypeRecord([("estimate", FRTypeDist), ("answer", FRTypeDistOrNumber)])], ~inputs=[FRTypeRecord([("estimate", FRTypeDist), ("answer", FRTypeDistOrNumber)])],
~run=(_, inputs, environment, _) => { ~run=(inputs, _, environment, _) => {
switch FunctionRegistry_Helpers.Prepare.ToValueArray.Record.twoArgs(inputs) { switch FunctionRegistry_Helpers.Prepare.ToValueArray.Record.twoArgs(inputs, ("estimate", "answer")) {
| Ok([FRValueDist(estimate), FRValueDistOrNumber(FRValueDist(d))]) => | Ok([IEvDistribution(estimate), IEvDistribution(d)]) =>
runScoring(estimate, Score_Dist(d), None, environment) 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) runScoring(estimate, Score_Scalar(d), None, environment)
| Error(e) => Error(e->FunctionRegistry_Helpers.wrapError) | Error(e) => Error(e->FunctionRegistry_Helpers.wrapError)
| _ => Error(FunctionRegistry_Helpers.impossibleError) | _ => Error(FunctionRegistry_Helpers.impossibleError)
@ -74,9 +74,9 @@ let library = [
FnDefinition.make( FnDefinition.make(
~name="klDivergence", ~name="klDivergence",
~inputs=[FRTypeDist, FRTypeDist], ~inputs=[FRTypeDist, FRTypeDist],
~run=(_, inputs, environment, _) => { ~run=(inputs, _, environment, _) => {
switch inputs { switch inputs {
| [FRValueDist(estimate), FRValueDist(d)] => | [IEvDistribution(estimate), IEvDistribution(d)] =>
runScoring(estimate, Score_Dist(d), None, environment) runScoring(estimate, Score_Dist(d), None, environment)
| _ => Error(FunctionRegistry_Helpers.impossibleError) | _ => Error(FunctionRegistry_Helpers.impossibleError)
} }

View File

@ -23,35 +23,14 @@ type rec frType =
and frTypeRecord = array<frTypeRecordParam> and frTypeRecord = array<frTypeRecordParam>
and frTypeRecordParam = (string, frType) and frTypeRecordParam = (string, frType)
/* type frValueDistOrNumber = FRValueNumber(float) | FRValueDist(DistributionTypes.genericDist)
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<frValue>)
| FRValueDistOrNumber(frValueDistOrNumber)
| FRValueRecord(frValueRecord)
| FRValueLambda(Reducer_T.lambdaValue)
| FRValueString(string)
| FRValueVariant(string)
| FRValueAny(frValue)
| FRValueDict(Js.Dict.t<frValue>)
and frValueRecord = array<frValueRecordParam>
and frValueRecordParam = (string, frValue)
and frValueDictParam = (string, frValue)
and frValueDistOrNumber = FRValueNumber(float) | FRValueDist(DistributionTypes.genericDist)
type fnDefinition = { type fnDefinition = {
name: string, name: string,
inputs: array<frType>, inputs: array<frType>,
run: ( run: (
array<Reducer_T.value>, array<Reducer_T.value>,
array<frValue>, unit,
Reducer_T.environment, Reducer_T.environment,
Reducer_T.reducerFn, Reducer_T.reducerFn,
) => result<Reducer_T.value, errorValue>, ) => result<Reducer_T.value, errorValue>,
@ -91,104 +70,43 @@ module FRType = {
| FRTypeAny => `any` | FRTypeAny => `any`
} }
let rec toFrValue = (r: Reducer_T.value): option<frValue> => let rec matchWithValue = (t: t, r: Reducer_T.value): bool =>
// 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<frValue> =>
switch (t, r) { switch (t, r) {
| (FRTypeAny, f) => toFrValue(f) | (FRTypeAny, _) => true
| (FRTypeString, IEvString(f)) => Some(FRValueString(f)) | (FRTypeString, IEvString(_)) => true
| (FRTypeNumber, IEvNumber(f)) => Some(FRValueNumber(f)) | (FRTypeNumber, IEvNumber(_)) => true
| (FRTypeBool, IEvBool(f)) => Some(FRValueBool(f)) | (FRTypeBool, IEvBool(_)) => true
| (FRTypeDate, IEvDate(f)) => Some(FRValueDate(f)) | (FRTypeDate, IEvDate(_)) => true
| (FRTypeTimeDuration, IEvTimeDuration(f)) => Some(FRValueTimeDuration(f)) | (FRTypeTimeDuration, IEvTimeDuration(_)) => true
| (FRTypeDistOrNumber, IEvNumber(f)) => Some(FRValueDistOrNumber(FRValueNumber(f))) | (FRTypeDistOrNumber, IEvNumber(_)) => true
| (FRTypeDistOrNumber, IEvDistribution(Symbolic(#Float(f)))) => | (FRTypeDistOrNumber, IEvDistribution(_)) => true
Some(FRValueDistOrNumber(FRValueNumber(f))) | (FRTypeDist, IEvDistribution(_)) => true
| (FRTypeDistOrNumber, IEvDistribution(f)) => Some(FRValueDistOrNumber(FRValueDist(f))) | (FRTypeNumeric, IEvNumber(_)) => true
| (FRTypeDist, IEvDistribution(f)) => Some(FRValueDist(f)) | (FRTypeNumeric, IEvDistribution(Symbolic(#Float(_)))) => true
| (FRTypeNumeric, IEvNumber(f)) => Some(FRValueNumber(f)) | (FRTypeLambda, IEvLambda(_)) => true
| (FRTypeNumeric, IEvDistribution(Symbolic(#Float(f)))) => Some(FRValueNumber(f))
| (FRTypeLambda, IEvLambda(f)) => Some(FRValueLambda(f))
| (FRTypeArray(intendedType), IEvArray(elements)) => { | (FRTypeArray(intendedType), IEvArray(elements)) => {
let el = elements->E.A2.fmap(matchWithExpressionValue(intendedType)) elements->Belt.Array.every(v => matchWithValue(intendedType, v))
E.A.O.openIfAllSome(el)->E.O2.fmap(r => FRValueArray(r))
} }
| (FRTypeDict(r), IEvRecord(map)) => | (FRTypeDict(r), IEvRecord(map)) =>
map map->Belt.Map.String.valuesToArray->Belt.Array.every(v => matchWithValue(r, v))
->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)))
| (FRTypeRecord(recordParams), IEvRecord(map)) => { | (FRTypeRecord(recordParams), IEvRecord(map)) => {
let getAndMatch = (name, input) => recordParams->Belt.Array.every(((name, input)) => {
Belt.Map.String.get(map, name)->E.O.bind(matchWithExpressionValue(input)) switch map->Belt.Map.String.get(name) {
//All names in the type must be present. If any are missing, the corresponding | Some(v) => matchWithValue(input, v)
//value will be None, and this function would return None. | None => false
let namesAndValues: array<option<(Js.Dict.key, frValue)>> =
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 })
}
| _ => false
} }
let rec matchReverse = (e: frValue): Reducer_T.value => let matchWithValueArray = (inputs: array<t>, args: array<Reducer_T.value>): bool => {
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<t>, args: array<Reducer_T.value>): option<
array<frValue>,
> => {
let isSameLength = E.A.length(inputs) == E.A.length(args) let isSameLength = E.A.length(inputs) == E.A.length(args)
if !isSameLength { if !isSameLength {
None false
} else { } else {
E.A.zip(inputs, args) E.A.zip(inputs, args)
->E.A2.fmap(((input, arg)) => matchWithExpressionValue(input, arg)) ->Belt.Array.every(((input, arg)) => matchWithValue(input, arg))
->E.A.O.openIfAllSome
} }
} }
} }
@ -202,11 +120,7 @@ module FnDefinition = {
} }
let isMatch = (t: t, args: array<Reducer_T.value>) => { let isMatch = (t: t, args: array<Reducer_T.value>) => {
let argValues = FRType.matchWithExpressionValueArray(t.inputs, args) FRType.matchWithValueArray(t.inputs, args)
switch argValues {
| Some(_) => true
| None => false
}
} }
let run = ( let run = (
@ -215,10 +129,9 @@ module FnDefinition = {
env: Reducer_T.environment, env: Reducer_T.environment,
reducer: Reducer_T.reducerFn, reducer: Reducer_T.reducerFn,
) => { ) => {
let argValues = FRType.matchWithExpressionValueArray(t.inputs, args) switch t->isMatch(args) {
switch argValues { | true => t.run(args, (), env, reducer)
| Some(values) => t.run(args, values, env, reducer) | false => REOther("Incorrect Types")->Error
| None => REOther("Incorrect Types")->Error
} }
} }

View File

@ -21,27 +21,30 @@ module Wrappers = {
let getOrError = (a, g) => E.A.get(a, g) |> E.O.toResult(impossibleErrorString) let getOrError = (a, g) => E.A.get(a, g) |> E.O.toResult(impossibleErrorString)
module Prepare = { module Prepare = {
type t = frValue type t = value
type ts = array<frValue> type ts = array<value>
type err = string type err = string
module ToValueArray = { module ToValueArray = {
module Record = { module Record = {
let twoArgs = (inputs: ts): result<ts, err> => let twoArgs = (inputs: ts, (arg1: string, arg2: string)): result<ts, err> =>
switch inputs { 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) | _ => Error(impossibleErrorString)
} }
let threeArgs = (inputs: ts): result<ts, err> => let threeArgs = (inputs: ts, (arg1: string, arg2: string, arg3: string)): result<ts, err> =>
switch inputs { switch inputs {
| [FRValueRecord([(_, n1), (_, n2), (_, n3)])] => Ok([n1, n2, n3]) | [IEvRecord(map)] => {
| _ => Error(impossibleErrorString) 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<ts, err> =>
switch inputs {
| [FRValueRecord(args)] => args->E.A2.fmap(((_, b)) => b)->Ok
| _ => Error(impossibleErrorString) | _ => Error(impossibleErrorString)
} }
} }
@ -49,13 +52,13 @@ module Prepare = {
module Array = { module Array = {
let openA = (inputs: t): result<ts, err> => let openA = (inputs: t): result<ts, err> =>
switch inputs { switch inputs {
| FRValueArray(n) => Ok(n) | IEvArray(n) => Ok(n)
| _ => Error(impossibleErrorString) | _ => Error(impossibleErrorString)
} }
let arrayOfArrays = (inputs: t): result<array<ts>, err> => let arrayOfArrays = (inputs: t): result<array<ts>, err> =>
switch inputs { 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) | _ => Error(impossibleErrorString)
} }
} }
@ -64,7 +67,10 @@ module Prepare = {
module ToValueTuple = { module ToValueTuple = {
let twoDistOrNumber = (values: ts): result<(frValueDistOrNumber, frValueDistOrNumber), err> => { let twoDistOrNumber = (values: ts): result<(frValueDistOrNumber, frValueDistOrNumber), err> => {
switch values { 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) | _ => Error(impossibleErrorString)
} }
} }
@ -74,66 +80,54 @@ module Prepare = {
err, err,
> => { > => {
switch values { switch values {
| [FRValueDist(a1), FRValueDist(a2)] => Ok(a1, a2) | [IEvDistribution(a1), IEvDistribution(a2)] => Ok(a1, a2)
| _ => Error(impossibleErrorString) | _ => Error(impossibleErrorString)
} }
} }
let twoNumbers = (values: ts): result<(float, float), err> => { let twoNumbers = (values: ts): result<(float, float), err> => {
switch values { switch values {
| [FRValueNumber(a1), FRValueNumber(a2)] => Ok(a1, a2) | [IEvNumber(a1), IEvNumber(a2)] => Ok(a1, a2)
| _ => Error(impossibleErrorString) | _ => Error(impossibleErrorString)
} }
} }
let threeNumbers = (values: ts): result<(float, float, float), err> => { let threeNumbers = (values: ts): result<(float, float, float), err> => {
switch values { switch values {
| [FRValueNumber(a1), FRValueNumber(a2), FRValueNumber(a3)] => Ok(a1, a2, a3) | [IEvNumber(a1), IEvNumber(a2), IEvNumber(a3)] => Ok(a1, a2, a3)
| _ => Error(impossibleErrorString) | _ => Error(impossibleErrorString)
} }
} }
let oneDistOrNumber = (values: ts): result<frValueDistOrNumber, err> => { let oneDistOrNumber = (values: ts): result<frValueDistOrNumber, err> => {
switch values { switch values {
| [FRValueDistOrNumber(a1)] => Ok(a1) | [IEvNumber(a1)] => FRValueNumber(a1)->Ok
| [IEvDistribution(a2)] => FRValueDist(a2)->Ok
| _ => Error(impossibleErrorString) | _ => Error(impossibleErrorString)
} }
} }
module Record = { module Record = {
let twoDistOrNumber = (values: ts): result<(frValueDistOrNumber, frValueDistOrNumber), err> => let twoDistOrNumber = (values: ts, labels: (string, string)): result<(frValueDistOrNumber, frValueDistOrNumber), err> =>
values->ToValueArray.Record.twoArgs->E.R.bind(twoDistOrNumber) 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), (DistributionTypes.genericDist, DistributionTypes.genericDist),
err, err,
> => values->ToValueArray.Record.twoArgs->E.R.bind(twoDist) > => values->ToValueArray.Record.twoArgs(labels)->E.R.bind(twoDist)
} }
} }
module ToArrayRecordPairs = { let oneNumber = (value: t): result<float, err> => {
let twoArgs = (input: t): result<array<ts>, err> => { switch value {
let array = input->ToValueArray.Array.openA | IEvNumber(a1) => Ok(a1)
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<float, err> => {
switch values {
| FRValueNumber(a1) => Ok(a1)
| _ => Error(impossibleErrorString) | _ => Error(impossibleErrorString)
} }
} }
let oneDict = (values: t): result<Js.Dict.t<frValue>, err> => { let oneDict = (value: t): result<Reducer_T.map, err> => {
switch values { switch value {
| FRValueDict(a1) => Ok(a1) | IEvRecord(a1) => Ok(a1)
| _ => Error(impossibleErrorString) | _ => Error(impossibleErrorString)
} }
} }
@ -145,7 +139,7 @@ module Prepare = {
inputs->getOrError(0)->E.R.bind(ToValueArray.Array.openA)->E.R.bind(openNumbers) inputs->getOrError(0)->E.R.bind(ToValueArray.Array.openA)->E.R.bind(openNumbers)
} }
let dicts = (inputs: ts): Belt.Result.t<array<Js.Dict.t<frValue>>, err> => { let dicts = (inputs: ts): Belt.Result.t<array<Reducer_T.map>, err> => {
let openDicts = (elements: array<t>) => elements->E.A2.fmap(oneDict)->E.A.R.firstErrorOrOpen let openDicts = (elements: array<t>) => elements->E.A2.fmap(oneDict)->E.A.R.firstErrorOrOpen
inputs->getOrError(0)->E.R.bind(ToValueArray.Array.openA)->E.R.bind(openDicts) inputs->getOrError(0)->E.R.bind(ToValueArray.Array.openA)->E.R.bind(openDicts)
} }