Full attempt at getting genericDist into Reducer External Lib

This commit is contained in:
Ozzie Gooen 2022-03-31 19:58:08 -04:00
parent cd231cb917
commit 5ece2994ba
4 changed files with 135 additions and 30 deletions

View File

@ -48,12 +48,24 @@ module OutputLocal = {
| _ => None
}
let toFloatR = (t: t): result<float, error> =>
switch t {
| Float(r) => Ok(r)
| e => Error(toErrorOrUnreachable(e))
}
let toString = (t: t) =>
switch t {
| String(d) => Some(d)
| _ => None
}
let toStringR = (t: t): result<string, error> =>
switch t {
| String(r) => Ok(r)
| e => Error(toErrorOrUnreachable(e))
}
//This is used to catch errors in other switch statements.
let fromResult = (r: result<t, error>): outputType =>
switch r {

View File

@ -26,7 +26,9 @@ module Output: {
let toDist: t => option<GenericDist_Types.genericDist>
let toDistR: t => result<GenericDist_Types.genericDist, GenericDist_Types.error>
let toFloat: t => option<float>
let toFloatR: t => result<float, GenericDist_Types.error>
let toString: t => option<string>
let toStringR: t => result<string, GenericDist_Types.error>
let toError: t => option<GenericDist_Types.error>
let fmap: (~env: env, t, GenericDist_Types.Operation.singleParamaterFunction) => t
}

View File

@ -36,7 +36,7 @@ let rec toString = aValue =>
->Js.String.concatMany("")
`{${pairs}}`
}
// | Dist() =>
| EvDist(dist) => `${GenericDist.toString(dist)}`
}
let toStringWithType = aValue =>
@ -47,7 +47,7 @@ let toStringWithType = aValue =>
| EvSymbol(_) => `Symbol::${toString(aValue)}`
| EvArray(_) => `Array::${toString(aValue)}`
| EvRecord(_) => `Record::${toString(aValue)}`
// | Dist(_) =>
| EvDist(_) => `Distribution::${toString(aValue)}`
}
let argsToString = (args: array<expressionValue>): string => {

View File

@ -10,38 +10,130 @@ 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<expressionValue>): 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<result<expressionValue, 'e>> => {
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 env: GenericDist_GenericOperation.env = {
sampleCount: 100,
xyPointLength: 100,
}
let dispatch = (call: ExpressionValue.functionCall, chain): result<expressionValue, 'e> =>
switch call {
| ("add", [EvNumber(a), EvNumber(b)]) => Sample.customAdd(a, b)->EvNumber->Ok
| ("add", [EvDist(a), EvDist(b)]) => {
let x = GenericDist_GenericOperation.Output.toDistR(
GenericDist_GenericOperation.run(~env, FromDist(ToDistCombination(Algebraic, #Add, #Dist(b)), a))
)
switch x {
| Ok(thing) => Ok(EvDist(thing))
| Error(err) => Error(Reducer_ErrorValue.RETodo("")) // TODO:
}
}
| ("add", [EvNumber(a), EvDist(b)]) => {
let x = GenericDist_GenericOperation.Output.toDistR(
GenericDist_GenericOperation.run(~env, FromDist(ToDistCombination(Algebraic, #Add, #Dist(b)), a))
)
switch x {
| Ok(thing) => Ok(EvDist(thing))
| Error(err) => Error(Reducer_ErrorValue.RETodo("")) // TODO:
}
}
| call => chain(call)
/*
Dist.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.
The final chain(call) invokes the builtin default functions of the interpreter.
@ -57,4 +149,3 @@ Remember from the users point of view, there are no different modules:
// "doSth( constructorType2 )"
doSth gets dispatched to the correct module because of the type signature. You get function and operator abstraction for free. You don't need to combine different implementations into one type. That would be duplicating the repsonsibility of the dispatcher.
*/
}