Split up function definitions

This commit is contained in:
Ozzie Gooen 2022-07-14 13:31:48 -07:00
parent 04accf0075
commit cae59cb84b
2 changed files with 726 additions and 596 deletions

View File

@ -213,93 +213,3 @@ module Process = {
twoValues(~fn=Helpers.wrapSymbolic(fn), ~values) twoValues(~fn=Helpers.wrapSymbolic(fn), ~values)
} }
} }
module TwoArgDist = {
let process = (~fn, ~env, r) =>
r
->E.R.bind(Process.DistOrNumberToDist.twoValuesUsingSymbolicDist(~fn, ~values=_, ~env))
->E.R2.fmap(Wrappers.evDistribution)
let make = (name, fn) => {
FnDefinition.make(
~name,
~inputs=[FRTypeDistOrNumber, FRTypeDistOrNumber],
~run=(inputs, env) => inputs->Prepare.ToValueTuple.twoDistOrNumber->process(~fn, ~env),
(),
)
}
let makeRecordP5P95 = (name, fn) => {
FnDefinition.make(
~name,
~inputs=[FRTypeRecord([("p5", FRTypeDistOrNumber), ("p95", FRTypeDistOrNumber)])],
~run=(inputs, env) => inputs->Prepare.ToValueTuple.Record.twoDistOrNumber->process(~fn, ~env),
(),
)
}
let makeRecordMeanStdev = (name, fn) => {
FnDefinition.make(
~name,
~inputs=[FRTypeRecord([("mean", FRTypeDistOrNumber), ("stdev", FRTypeDistOrNumber)])],
~run=(inputs, env) => inputs->Prepare.ToValueTuple.Record.twoDistOrNumber->process(~fn, ~env),
(),
)
}
}
module OneArgDist = {
let process = (~fn, ~env, r) =>
r
->E.R.bind(Process.DistOrNumberToDist.oneValueUsingSymbolicDist(~fn, ~value=_, ~env))
->E.R2.fmap(Wrappers.evDistribution)
let make = (name, fn) =>
FnDefinition.make(
~name,
~inputs=[FRTypeDistOrNumber],
~run=(inputs, env) => inputs->Prepare.ToValueTuple.oneDistOrNumber->process(~fn, ~env),
(),
)
}
module ArrayNumberDist = {
let make = (name, fn) => {
FnDefinition.make(
~name,
~inputs=[FRTypeArray(FRTypeNumber)],
~run=(inputs, _) =>
Prepare.ToTypedArray.numbers(inputs)
->E.R.bind(r => E.A.length(r) === 0 ? Error("List is empty") : Ok(r))
->E.R.bind(fn),
(),
)
}
let make2 = (name, fn) => {
FnDefinition.make(
~name,
~inputs=[FRTypeArray(FRTypeAny)],
~run=(inputs, _) =>
Prepare.ToTypedArray.numbers(inputs)
->E.R.bind(r => E.A.length(r) === 0 ? Error("List is empty") : Ok(r))
->E.R.bind(fn),
(),
)
}
}
module NumberToNumber = {
let make = (name, fn) =>
FnDefinition.make(
~name,
~inputs=[FRTypeNumber],
~run=(inputs, _) => {
inputs
->getOrError(0)
->E.R.bind(Prepare.oneNumber)
->E.R2.fmap(fn)
->E.R2.fmap(Wrappers.evNumber)
},
(),
)
}

View File

@ -49,13 +49,16 @@ let inputsTodist = (inputs: array<FunctionRegistry_Core.frValue>, makeDist) => {
expressionValue expressionValue
} }
let registryStart = [ module PointSet = {
let nameSpace = Some("PointSet")
let requiresNamespace = true
let library = [
Function.make( Function.make(
~name="toContinuousPointSet", ~name="PointSet.makeContinuous",
~definitions=[ ~definitions=[
FnDefinition.make( FnDefinition.make(
~nameSpace=Some("PointSet"), ~nameSpace,
~requiresNamespace=true, ~requiresNamespace,
~name="makeContinuous", ~name="makeContinuous",
~inputs=[FRTypeArray(FRTypeRecord([("x", FRTypeNumeric), ("y", FRTypeNumeric)]))], ~inputs=[FRTypeArray(FRTypeRecord([("x", FRTypeNumeric), ("y", FRTypeNumeric)]))],
~run=(inputs, _) => inputsTodist(inputs, r => Continuous(Continuous.make(r))), ~run=(inputs, _) => inputsTodist(inputs, r => Continuous(Continuous.make(r))),
@ -65,11 +68,11 @@ let registryStart = [
(), (),
), ),
Function.make( Function.make(
~name="toDiscretePointSet", ~name="PointSet.makeDiscrete",
~definitions=[ ~definitions=[
FnDefinition.make( FnDefinition.make(
~nameSpace=Some("PointSet"), ~nameSpace,
~requiresNamespace=true, ~requiresNamespace,
~name="makeDiscrete", ~name="makeDiscrete",
~inputs=[FRTypeArray(FRTypeRecord([("x", FRTypeNumeric), ("y", FRTypeNumeric)]))], ~inputs=[FRTypeArray(FRTypeRecord([("x", FRTypeNumeric), ("y", FRTypeNumeric)]))],
~run=(inputs, _) => inputsTodist(inputs, r => Discrete(Discrete.make(r))), ~run=(inputs, _) => inputsTodist(inputs, r => Discrete(Discrete.make(r))),
@ -78,11 +81,19 @@ let registryStart = [
], ],
(), (),
), ),
]
}
module Functionn = {
let nameSpace = Some("Function")
let library = [
Function.make( Function.make(
~name="Declaration", ~name="Function.declare",
~definitions=[ ~definitions=[
FnDefinition.make( FnDefinition.make(
~name="declareFn", ~nameSpace,
~requiresNamespace=true,
~name="declare",
~inputs=[Declaration.frType], ~inputs=[Declaration.frType],
~run=(inputs, _) => { ~run=(inputs, _) => {
inputs->getOrError(0)->E.R.bind(Declaration.fromExpressionValue) inputs->getOrError(0)->E.R.bind(Declaration.fromExpressionValue)
@ -92,6 +103,70 @@ let registryStart = [
], ],
(), (),
), ),
]
}
module DistributionCreation = {
let nameSpace = Some("Dist")
module TwoArgDist = {
let process = (~fn, ~env, r) =>
r
->E.R.bind(Process.DistOrNumberToDist.twoValuesUsingSymbolicDist(~fn, ~values=_, ~env))
->E.R2.fmap(Wrappers.evDistribution)
let make = (name, fn) => {
FnDefinition.make(
~nameSpace,
~requiresNamespace=false,
~name,
~inputs=[FRTypeDistOrNumber, FRTypeDistOrNumber],
~run=(inputs, env) => inputs->Prepare.ToValueTuple.twoDistOrNumber->process(~fn, ~env),
(),
)
}
let makeRecordP5P95 = (name, fn) => {
FnDefinition.make(
~nameSpace,
~requiresNamespace=false,
~name,
~inputs=[FRTypeRecord([("p5", FRTypeDistOrNumber), ("p95", FRTypeDistOrNumber)])],
~run=(inputs, env) =>
inputs->Prepare.ToValueTuple.Record.twoDistOrNumber->process(~fn, ~env),
(),
)
}
let makeRecordMeanStdev = (name, fn) => {
FnDefinition.make(
~name,
~nameSpace,
~requiresNamespace=false,
~inputs=[FRTypeRecord([("mean", FRTypeDistOrNumber), ("stdev", FRTypeDistOrNumber)])],
~run=(inputs, env) =>
inputs->Prepare.ToValueTuple.Record.twoDistOrNumber->process(~fn, ~env),
(),
)
}
}
module OneArgDist = {
let process = (~fn, ~env, r) =>
r
->E.R.bind(Process.DistOrNumberToDist.oneValueUsingSymbolicDist(~fn, ~value=_, ~env))
->E.R2.fmap(Wrappers.evDistribution)
let make = (name, fn) =>
FnDefinition.make(
~nameSpace,
~requiresNamespace=false,
~name,
~inputs=[FRTypeDistOrNumber],
~run=(inputs, env) => inputs->Prepare.ToValueTuple.oneDistOrNumber->process(~fn, ~env),
(),
)
}
let library = [
Function.make( Function.make(
~name="Normal", ~name="Normal",
~examples=`normal(5,1) ~examples=`normal(5,1)
@ -99,10 +174,10 @@ normal({p5: 4, p95: 10})
normal({mean: 5, stdev: 2})`, normal({mean: 5, stdev: 2})`,
~definitions=[ ~definitions=[
TwoArgDist.make("normal", twoArgs(SymbolicDist.Normal.make)), TwoArgDist.make("normal", twoArgs(SymbolicDist.Normal.make)),
TwoArgDist.makeRecordP5P95("normal", r => // TwoArgDist.makeRecordP5P95("normal", r =>
twoArgs(SymbolicDist.Normal.from90PercentCI, r)->Ok // twoArgs(SymbolicDist.Normal.from90PercentCI, r)->Ok
), // ),
TwoArgDist.makeRecordMeanStdev("normal", twoArgs(SymbolicDist.Normal.make)), // TwoArgDist.makeRecordMeanStdev("normal", twoArgs(SymbolicDist.Normal.make)),
], ],
(), (),
), ),
@ -116,7 +191,10 @@ lognormal({mean: 5, stdev: 2})`,
TwoArgDist.makeRecordP5P95("lognormal", r => TwoArgDist.makeRecordP5P95("lognormal", r =>
twoArgs(SymbolicDist.Lognormal.from90PercentCI, r)->Ok twoArgs(SymbolicDist.Lognormal.from90PercentCI, r)->Ok
), ),
TwoArgDist.makeRecordMeanStdev("lognormal", twoArgs(SymbolicDist.Lognormal.fromMeanAndStdev)), TwoArgDist.makeRecordMeanStdev(
"lognormal",
twoArgs(SymbolicDist.Lognormal.fromMeanAndStdev),
),
], ],
(), (),
), ),
@ -186,6 +264,10 @@ to(5,10)
~definitions=[OneArgDist.make("pointMass", SymbolicDist.Float.makeSafe)], ~definitions=[OneArgDist.make("pointMass", SymbolicDist.Float.makeSafe)],
(), (),
), ),
]
}
let registryStart = [
Function.make( Function.make(
~name="toContinuousPointSet", ~name="toContinuousPointSet",
~description="Converts a set of points to a continuous distribution", ~description="Converts a set of points to a continuous distribution",
@ -247,6 +329,58 @@ to(5,10)
~isExperimental=true, ~isExperimental=true,
(), (),
), ),
]
module Number = {
let nameSpace = Some("Number")
let requiresNamespace = false
module NumberToNumber = {
let make = (name, fn) =>
FnDefinition.make(
~nameSpace,
~requiresNamespace,
~name,
~inputs=[FRTypeNumber],
~run=(inputs, _) => {
inputs
->getOrError(0)
->E.R.bind(Prepare.oneNumber)
->E.R2.fmap(fn)
->E.R2.fmap(Wrappers.evNumber)
},
(),
)
}
module ArrayNumberDist = {
let make = (name, fn) => {
FnDefinition.make(
~nameSpace,
~requiresNamespace=false,
~name,
~inputs=[FRTypeArray(FRTypeNumber)],
~run=(inputs, _) =>
Prepare.ToTypedArray.numbers(inputs)
->E.R.bind(r => E.A.length(r) === 0 ? Error("List is empty") : Ok(r))
->E.R.bind(fn),
(),
)
}
let make2 = (name, fn) => {
FnDefinition.make(
~name,
~inputs=[FRTypeArray(FRTypeAny)],
~run=(inputs, _) =>
Prepare.ToTypedArray.numbers(inputs)
->E.R.bind(r => E.A.length(r) === 0 ? Error("List is empty") : Ok(r))
->E.R.bind(fn),
(),
)
}
}
let library = [
Function.make( Function.make(
~name="Floor", ~name="Floor",
~definitions=[NumberToNumber.make("floor", Js.Math.floor_float)], ~definitions=[NumberToNumber.make("floor", Js.Math.floor_float)],
@ -317,24 +451,6 @@ to(5,10)
], ],
(), (),
), ),
Function.make(
~name="First",
~definitions=[
ArrayNumberDist.make2("first", r =>
r->E.A.first |> E.O.toResult(impossibleError) |> E.R.fmap(Wrappers.evNumber)
),
],
(),
),
Function.make(
~name="Last",
~definitions=[
ArrayNumberDist.make2("last", r =>
r->E.A.last |> E.O.toResult(impossibleError) |> E.R.fmap(Wrappers.evNumber)
),
],
(),
),
Function.make( Function.make(
~name="Sort", ~name="Sort",
~definitions=[ ~definitions=[
@ -344,15 +460,6 @@ to(5,10)
], ],
(), (),
), ),
Function.make(
~name="Reverse",
~definitions=[
ArrayNumberDist.make("reverse", r =>
r->Belt_Array.reverse->E.A2.fmap(Wrappers.evNumber)->Wrappers.evArray->Ok
),
],
(),
),
Function.make( Function.make(
~name="Cumulative Sum", ~name="Cumulative Sum",
~definitions=[ ~definitions=[
@ -380,11 +487,17 @@ to(5,10)
], ],
(), (),
), ),
]
}
module Dict = {
let nameSpace = Some("Dict")
let library = [
Function.make( Function.make(
~name="Dict.merge", ~name="merge",
~definitions=[ ~definitions=[
FnDefinition.make( FnDefinition.make(
~nameSpace=Some("Dict"), ~nameSpace,
~requiresNamespace=true, ~requiresNamespace=true,
~name="merge", ~name="merge",
~inputs=[FRTypeDict(FRTypeAny), FRTypeDict(FRTypeAny)], ~inputs=[FRTypeDict(FRTypeAny), FRTypeDict(FRTypeAny)],
@ -407,10 +520,10 @@ to(5,10)
), ),
//TODO: Make sure that two functions can't have the same name. This causes chaos elsewhere. //TODO: Make sure that two functions can't have the same name. This causes chaos elsewhere.
Function.make( Function.make(
~name="Dict.mergeMany", ~name="mergeMany",
~definitions=[ ~definitions=[
FnDefinition.make( FnDefinition.make(
~nameSpace=Some("Dict"), ~nameSpace,
~requiresNamespace=true, ~requiresNamespace=true,
~name="mergeMany", ~name="mergeMany",
~inputs=[FRTypeArray(FRTypeDict(FRTypeAny))], ~inputs=[FRTypeArray(FRTypeDict(FRTypeAny))],
@ -427,10 +540,10 @@ to(5,10)
(), (),
), ),
Function.make( Function.make(
~name="Dict.keys", ~name="keys",
~definitions=[ ~definitions=[
FnDefinition.make( FnDefinition.make(
~nameSpace=Some("Dict"), ~nameSpace,
~requiresNamespace=true, ~requiresNamespace=true,
~name="keys", ~name="keys",
~inputs=[FRTypeDict(FRTypeAny)], ~inputs=[FRTypeDict(FRTypeAny)],
@ -446,10 +559,10 @@ to(5,10)
(), (),
), ),
Function.make( Function.make(
~name="Dict.values", ~name="values",
~definitions=[ ~definitions=[
FnDefinition.make( FnDefinition.make(
~nameSpace=Some("Dict"), ~nameSpace,
~requiresNamespace=true, ~requiresNamespace=true,
~name="values", ~name="values",
~inputs=[FRTypeDict(FRTypeAny)], ~inputs=[FRTypeDict(FRTypeAny)],
@ -468,10 +581,10 @@ to(5,10)
(), (),
), ),
Function.make( Function.make(
~name="Dict.toList", ~name="toList",
~definitions=[ ~definitions=[
FnDefinition.make( FnDefinition.make(
~nameSpace=Some("Dict"), ~nameSpace,
~requiresNamespace=true, ~requiresNamespace=true,
~name="toList", ~name="toList",
~inputs=[FRTypeDict(FRTypeAny)], ~inputs=[FRTypeDict(FRTypeAny)],
@ -496,10 +609,10 @@ to(5,10)
(), (),
), ),
Function.make( Function.make(
~name="Dict.fromList", ~name="fromList",
~definitions=[ ~definitions=[
FnDefinition.make( FnDefinition.make(
~nameSpace=Some("Dict"), ~nameSpace,
~requiresNamespace=true, ~requiresNamespace=true,
~name="fromList", ~name="fromList",
~inputs=[FRTypeArray(FRTypeArray(FRTypeAny))], ~inputs=[FRTypeArray(FRTypeArray(FRTypeAny))],
@ -524,13 +637,21 @@ to(5,10)
], ],
(), (),
), ),
]
}
module List = {
let nameSpace = Some("List")
let requiresNamespace = true
let library = [
Function.make( Function.make(
~name="List.make", ~name="List.make",
~definitions=[ ~definitions=[
//Todo: If the second item is a function with no args, it could be nice to run this function and return the result. //Todo: If the second item is a function with no args, it could be nice to run this function and return the result.
FnDefinition.make( FnDefinition.make(
~nameSpace=Some("List"), ~nameSpace,
~requiresNamespace=true, ~requiresNamespace,
~name="make", ~name="make",
~inputs=[FRTypeNumber, FRTypeAny], ~inputs=[FRTypeNumber, FRTypeAny],
~run=(inputs, _) => { ~run=(inputs, _) => {
@ -549,11 +670,11 @@ to(5,10)
(), (),
), ),
Function.make( Function.make(
~name="upTo", ~name="List.upTo",
~definitions=[ ~definitions=[
FnDefinition.make( FnDefinition.make(
~nameSpace=Some("List"), ~nameSpace,
~requiresNamespace=true, ~requiresNamespace,
~name="upTo", ~name="upTo",
~inputs=[FRTypeNumber, FRTypeNumber], ~inputs=[FRTypeNumber, FRTypeNumber],
~run=(inputs, _) => ~run=(inputs, _) =>
@ -569,19 +690,90 @@ to(5,10)
], ],
(), (),
), ),
] Function.make(
~name="List.first",
~definitions=[
FnDefinition.make(
~nameSpace,
~requiresNamespace,
~name="first",
~inputs=[FRTypeArray(FRTypeAny)],
~run=(inputs, _) =>
switch inputs {
| [FRValueArray(array)] =>
E.A.first(array)
|> E.O.toResult("No first element")
|> E.R.fmap(FunctionRegistry_Core.FRType.matchReverse)
| _ => Error(impossibleError)
},
(),
),
],
(),
),
Function.make(
~name="List.last",
~definitions=[
FnDefinition.make(
~nameSpace,
~requiresNamespace=false,
~name="last",
~inputs=[FRTypeArray(FRTypeAny)],
~run=(inputs, _) =>
switch inputs {
| [FRValueArray(array)] =>
E.A.last(array)
|> E.O.toResult("No first element")
|> E.R.fmap(FunctionRegistry_Core.FRType.matchReverse)
| _ => Error(impossibleError)
},
(),
),
],
(),
),
Function.make(
~name="List.reverse",
~definitions=[
FnDefinition.make(
~nameSpace,
~requiresNamespace=false,
~name="last",
~inputs=[FRTypeArray(FRTypeAny)],
~run=(inputs, _) =>
switch inputs {
| [FRValueArray(array)] =>
Belt.Array.reverse(array)
->E.A2.fmap(FunctionRegistry_Core.FRType.matchReverse)
->Wrappers.evArray
->Ok
| _ => Error(impossibleError)
},
(),
),
],
(),
),
]
}
let runScoring = (estimate, answer, prior, env) => { module Scoring = {
let nameSpace = Some("Dist")
let requiresNamespace = false
let runScoring = (estimate, answer, prior, env) => {
GenericDist.Score.logScore(~estimate, ~answer, ~prior, ~env) GenericDist.Score.logScore(~estimate, ~answer, ~prior, ~env)
->E.R2.fmap(FunctionRegistry_Helpers.Wrappers.evNumber) ->E.R2.fmap(FunctionRegistry_Helpers.Wrappers.evNumber)
->E.R2.errMap(DistributionTypes.Error.toString) ->E.R2.errMap(DistributionTypes.Error.toString)
} }
let scoreFunctions = [ let library = [
Function.make( Function.make(
~name="Score", ~name="logScore",
~definitions=[ ~definitions=[
FnDefinition.make( FnDefinition.make(
~nameSpace,
~requiresNamespace,
~name="logScore", ~name="logScore",
~inputs=[ ~inputs=[
FRTypeRecord([ FRTypeRecord([
@ -592,7 +784,11 @@ let scoreFunctions = [
], ],
~run=(inputs, env) => { ~run=(inputs, env) => {
switch FunctionRegistry_Helpers.Prepare.ToValueArray.Record.threeArgs(inputs) { switch FunctionRegistry_Helpers.Prepare.ToValueArray.Record.threeArgs(inputs) {
| Ok([FRValueDist(estimate), FRValueDistOrNumber(FRValueDist(d)), FRValueDist(prior)]) => | Ok([
FRValueDist(estimate),
FRValueDistOrNumber(FRValueDist(d)),
FRValueDist(prior),
]) =>
runScoring(estimate, Score_Dist(d), Some(prior), env) runScoring(estimate, Score_Dist(d), Some(prior), env)
| Ok([ | Ok([
FRValueDist(estimate), FRValueDist(estimate),
@ -604,9 +800,12 @@ let scoreFunctions = [
| _ => Error(FunctionRegistry_Helpers.impossibleError) | _ => Error(FunctionRegistry_Helpers.impossibleError)
} }
}, },
(),
), ),
FnDefinition.make( FnDefinition.make(
~name="logScore", ~name="logScore",
~nameSpace,
~requiresNamespace,
~inputs=[FRTypeRecord([("estimate", FRTypeDist), ("answer", FRTypeDistOrNumber)])], ~inputs=[FRTypeRecord([("estimate", FRTypeDist), ("answer", FRTypeDistOrNumber)])],
~run=(inputs, env) => { ~run=(inputs, env) => {
switch FunctionRegistry_Helpers.Prepare.ToValueArray.Record.twoArgs(inputs) { switch FunctionRegistry_Helpers.Prepare.ToValueArray.Record.twoArgs(inputs) {
@ -618,19 +817,40 @@ let scoreFunctions = [
| _ => Error(FunctionRegistry_Helpers.impossibleError) | _ => Error(FunctionRegistry_Helpers.impossibleError)
} }
}, },
(),
), ),
FnDefinition.make(~name="klDivergence", ~inputs=[FRTypeDist, FRTypeDist], ~run=(
inputs,
env,
) => {
switch inputs {
| [FRValueDist(estimate), FRValueDist(d)] => runScoring(estimate, Score_Dist(d), None, env)
| _ => Error(FunctionRegistry_Helpers.impossibleError)
}
}),
], ],
(), (),
), ),
] Function.make(
~name="klDivergence",
~definitions=[
FnDefinition.make(
~name="klDivergence",
~nameSpace,
~requiresNamespace,
~inputs=[FRTypeDist, FRTypeDist],
~run=(inputs, env) => {
switch inputs {
| [FRValueDist(estimate), FRValueDist(d)] =>
runScoring(estimate, Score_Dist(d), None, env)
| _ => Error(FunctionRegistry_Helpers.impossibleError)
}
},
(),
),
],
(),
),
]
}
let registry = E.A.append(registryStart, scoreFunctions) let registry = Belt.Array.concatMany([
PointSet.library,
Functionn.library,
Number.library,
Dict.library,
List.library,
DistributionCreation.library,
Scoring.library,
])