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 | _ => None
} }
let toFloatR = (t: t): result<float, error> =>
switch t {
| Float(r) => Ok(r)
| e => Error(toErrorOrUnreachable(e))
}
let toString = (t: t) => let toString = (t: t) =>
switch t { switch t {
| String(d) => Some(d) | String(d) => Some(d)
| _ => None | _ => 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. //This is used to catch errors in other switch statements.
let fromResult = (r: result<t, error>): outputType => let fromResult = (r: result<t, error>): outputType =>
switch r { switch r {

View File

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

View File

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

View File

@ -10,38 +10,130 @@ module Sample = {
let customAdd = (a: float, b: float): float => {a +. b} 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 Map external calls of Reducer
*/ */
let env: GenericDist_GenericOperation.env = {
sampleCount: 100,
xyPointLength: 100,
}
let dispatch = (call: ExpressionValue.functionCall, chain): result<expressionValue, 'e> => let dispatch = (call: ExpressionValue.functionCall, chain): result<expressionValue, 'e> =>
switch call { Dist.dispatch(call) |> E.O.default(chain(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)
/*
If your dispatch is too big you can divide it into smaller dispatches and pass the call so that it gets called finally. 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. 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( 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. 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.
*/ */
}