diff --git a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_ExternalLibrary.res b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_ExternalLibrary.res index d4586978..063fd472 100644 --- a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_ExternalLibrary.res +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_ExternalLibrary.res @@ -10,129 +10,12 @@ module Sample = { let customAdd = (a: float, b: float): float => {a +. b} } -module Dist = { - let env: GenericDist_GenericOperation.env = { - sampleCount: 1000, - xyPointLength: 1000, - } - - let {toDistR, toFloatR} = module(GenericDist_GenericOperation.Output) - let runGenericOperation = GenericDist_GenericOperation.run(~env) - - let genericDistReturnToEvReturn = x => - switch x { - | Ok(thing) => Ok(ReducerInterface_ExpressionValue.EvDist(thing)) - | Error(err) => Error(Reducer_ErrorValue.RETodo("")) // TODO: - } - - let numberReturnToEvReturn = x => - switch x { - | Ok(n) => Ok(ReducerInterface_ExpressionValue.EvNumber(n)) - | Error(err) => Error(Reducer_ErrorValue.RETodo("")) // TODO: - } - - let arithmeticMap = r => - switch r { - | "add" => #Add - | "dotAdd" => #Add - | "subtract" => #Subtract - | "dotSubtract" => #Subtract - | "divide" => #Divide - | "logarithm" => #Divide - | "dotDivide" => #Divide - | "exponentiate" => #Exponentiate - | "dotExponentiate" => #Exponentiate - | "multiply" => #Multiply - | "dotMultiply" => #Multiply - | "dotLogarithm" => #Divide - | _ => #Multiply - } - - let catchAndConvertTwoArgsToDists = (args: array): option<( - GenericDist_Types.genericDist, - GenericDist_Types.genericDist, - )> => { - switch args { - | [EvDist(a), EvDist(b)] => Some((a, b)) - | [EvNumber(a), EvDist(b)] => Some((GenericDist.fromFloat(a), b)) - | [EvDist(a), EvNumber(b)] => Some((a, GenericDist.fromFloat(b))) - | _ => None - } - } - - let toFloatFn = (fnCall: GenericDist_Types.Operation.toFloat, dist) => { - FromDist(GenericDist_Types.Operation.ToFloat(fnCall), dist) - ->runGenericOperation - ->toFloatR - ->numberReturnToEvReturn - ->Some - } - - let toDistFn = (fnCall: GenericDist_Types.Operation.toDist, dist) => { - FromDist(GenericDist_Types.Operation.ToDist(fnCall), dist) - ->runGenericOperation - ->toDistR - ->genericDistReturnToEvReturn - ->Some - } - - let twoDiststoDistFn = (direction, arithmetic, dist1, dist2) => { - FromDist( - GenericDist_Types.Operation.ToDistCombination( - direction, - arithmeticMap(arithmetic), - #Dist(dist2), - ), - dist1, - ) - ->runGenericOperation - ->toDistR - ->genericDistReturnToEvReturn - } - - let dispatch = (call: ExpressionValue.functionCall): option> => { - let (fnName, args) = call - switch (fnName, args) { - | ("cdf", [EvDist(dist), EvNumber(float)]) => toFloatFn(#Cdf(float), dist) - | ("pdf", [EvDist(dist), EvNumber(float)]) => toFloatFn(#Pdf(float), dist) - | ("inv", [EvDist(dist), EvNumber(float)]) => toFloatFn(#Inv(float), dist) - | ("mean", [EvDist(dist)]) => toFloatFn(#Mean, dist) - | ("normalize", [EvDist(dist)]) => toDistFn(Normalize, dist) - | ("toPointSet", [EvDist(dist)]) => toDistFn(ToPointSet, dist) - | ("toSampleSet", [EvDist(dist), EvNumber(float)]) => - toDistFn(ToSampleSet(Belt.Int.fromFloat(float)), dist) - | ("truncateLeft", [EvDist(dist), EvNumber(float)]) => - toDistFn(Truncate(Some(float), None), dist) - | ("truncateRight", [EvDist(dist), EvNumber(float)]) => - toDistFn(Truncate(None, Some(float)), dist) - | ("truncate", [EvDist(dist), EvNumber(float1), EvNumber(float2)]) => - toDistFn(Truncate(Some(float1), Some(float2)), dist) - | ("sample", [EvDist(dist)]) => toFloatFn(#Sample, dist) - | ( - ("add" | "multiply" | "subtract" | "divide" | "exponentiate") as arithmetic, - [a, b] as args, - ) => - catchAndConvertTwoArgsToDists(args) |> E.O.fmap(((fst, snd)) => - twoDiststoDistFn(Algebraic, arithmetic, fst, snd) - ) - | ( - ("dotAdd" | "dotSubtract" | "dotDivide" | "dotExponentiate" | "dotMultiply") as arithmetic, - [a, b] as args, - ) => - catchAndConvertTwoArgsToDists(args) |> E.O.fmap(((fst, snd)) => - twoDiststoDistFn(Pointwise, arithmetic, fst, snd) - ) - | _ => None - } - } -} - /* Map external calls of Reducer */ let dispatch = (call: ExpressionValue.functionCall, chain): result => - Dist.dispatch(call) |> E.O.default(chain(call)) + ReducerInterface_GenericDistribution.dispatch(call) |> E.O.default(chain(call)) /* If your dispatch is too big you can divide it into smaller dispatches and pass the call so that it gets called finally. diff --git a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res new file mode 100644 index 00000000..eb5704ae --- /dev/null +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res @@ -0,0 +1,113 @@ +module ExpressionValue = ReducerInterface_ExpressionValue +type expressionValue = ReducerInterface_ExpressionValue.expressionValue + +let env: GenericDist_GenericOperation.env = { + sampleCount: 1000, + xyPointLength: 1000, +} + +let runGenericOperation = GenericDist_GenericOperation.run(~env) + +let arithmeticMap = r => + switch r { + | "add" => #Add + | "dotAdd" => #Add + | "subtract" => #Subtract + | "dotSubtract" => #Subtract + | "divide" => #Divide + | "logarithm" => #Divide + | "dotDivide" => #Divide + | "exponentiate" => #Exponentiate + | "dotExponentiate" => #Exponentiate + | "multiply" => #Multiply + | "dotMultiply" => #Multiply + | "dotLogarithm" => #Divide + | _ => #Multiply + } + +let catchAndConvertTwoArgsToDists = (args: array): option<( + GenericDist_Types.genericDist, + GenericDist_Types.genericDist, +)> => { + switch args { + | [EvDist(a), EvDist(b)] => Some((a, b)) + | [EvNumber(a), EvDist(b)] => Some((GenericDist.fromFloat(a), b)) + | [EvDist(a), EvNumber(b)] => Some((a, GenericDist.fromFloat(b))) + | _ => None + } +} + +let toFloatFn = ( + fnCall: GenericDist_Types.Operation.toFloat, + dist: GenericDist_Types.genericDist, +) => { + FromDist(GenericDist_Types.Operation.ToFloat(fnCall), dist)->runGenericOperation->Some +} + +let toDistFn = (fnCall: GenericDist_Types.Operation.toDist, dist) => { + FromDist(GenericDist_Types.Operation.ToDist(fnCall), dist)->runGenericOperation->Some +} + +let twoDiststoDistFn = (direction, arithmetic, dist1, dist2) => { + FromDist( + GenericDist_Types.Operation.ToDistCombination( + direction, + arithmeticMap(arithmetic), + #Dist(dist2), + ), + dist1, + )->runGenericOperation +} + +let genericOutputToReducerValue = (o: GenericDist_GenericOperation.outputType): result< + expressionValue, + Reducer_ErrorValue.errorValue, +> => + switch o { + | Dist(d) => Ok(ReducerInterface_ExpressionValue.EvDist(d)) + | Float(d) => Ok(EvNumber(d)) + | String(d) => Ok(EvString(d)) + | GenDistError(NotYetImplemented) => Error(RETodo("Function not yet implemented")) + | GenDistError(Unreachable) => Error(RETodo("Unreachable")) + | GenDistError(DistributionVerticalShiftIsInvalid) => + Error(RETodo("Distribution Vertical Shift is Invalid")) + | GenDistError(Other(s)) => Error(RETodo(s)) + } + +let dispatchToGenericOutput = (call: ExpressionValue.functionCall): option< + GenericDist_GenericOperation.outputType, +> => { + let (fnName, args) = call + switch (fnName, args) { + | ("sample", [EvDist(dist)]) => toFloatFn(#Sample, dist) + | ("mean", [EvDist(dist)]) => toFloatFn(#Mean, dist) + | ("normalize", [EvDist(dist)]) => toDistFn(Normalize, dist) + | ("toPointSet", [EvDist(dist)]) => toDistFn(ToPointSet, dist) + | ("cdf", [EvDist(dist), EvNumber(float)]) => toFloatFn(#Cdf(float), dist) + | ("pdf", [EvDist(dist), EvNumber(float)]) => toFloatFn(#Pdf(float), dist) + | ("inv", [EvDist(dist), EvNumber(float)]) => toFloatFn(#Inv(float), dist) + | ("toSampleSet", [EvDist(dist), EvNumber(float)]) => + toDistFn(ToSampleSet(Belt.Int.fromFloat(float)), dist) + | ("truncateLeft", [EvDist(dist), EvNumber(float)]) => toDistFn(Truncate(Some(float), None), dist) + | ("truncateRight", [EvDist(dist), EvNumber(float)]) => + toDistFn(Truncate(None, Some(float)), dist) + | ("truncate", [EvDist(dist), EvNumber(float1), EvNumber(float2)]) => + toDistFn(Truncate(Some(float1), Some(float2)), dist) + | (("add" | "multiply" | "subtract" | "divide" | "exponentiate") as arithmetic, [a, b] as args) => + catchAndConvertTwoArgsToDists(args) -> E.O2.fmap(((fst, snd)) => + twoDiststoDistFn(Algebraic, arithmetic, fst, snd) + ) + | ( + ("dotAdd" | "dotMultiply" | "dotSubtract" | "dotDivide" | "dotExponentiate") as arithmetic, + [a, b] as args, + ) => + catchAndConvertTwoArgsToDists(args) -> E.O2.fmap(((fst, snd)) => + twoDiststoDistFn(Pointwise, arithmetic, fst, snd) + ) + | _ => None + } +} + +let dispatch = call => { + dispatchToGenericOutput(call) -> E.O2.fmap(genericOutputToReducerValue) +} diff --git a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.resi b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.resi new file mode 100644 index 00000000..fc7ebabc --- /dev/null +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.resi @@ -0,0 +1,3 @@ +let dispatch: ReducerInterface_ExpressionValue.functionCall => option< + result, +> diff --git a/packages/squiggle-lang/src/rescript/utility/E.res b/packages/squiggle-lang/src/rescript/utility/E.res index 636cc600..e36b6124 100644 --- a/packages/squiggle-lang/src/rescript/utility/E.res +++ b/packages/squiggle-lang/src/rescript/utility/E.res @@ -100,6 +100,7 @@ module O = { module O2 = { let default = (a, b) => O.default(b, a) let toExn = (a, b) => O.toExn(b, a) + let fmap = (a, b) => O.fmap(b, a) } /* Functions */