squiggle/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Library.res

857 lines
23 KiB
Plaintext
Raw Normal View History

open FunctionRegistry_Core
open FunctionRegistry_Helpers
2022-05-21 15:41:12 +00:00
let twoArgs = E.Tuple2.toFnCall
2022-05-24 21:02:27 +00:00
module Declaration = {
2022-05-24 11:52:27 +00:00
let frType = FRTypeRecord([
("fn", FRTypeLambda),
("inputs", FRTypeArray(FRTypeRecord([("min", FRTypeNumber), ("max", FRTypeNumber)]))),
])
2022-06-24 10:15:38 +00:00
let fromExpressionValue = (e: frValue): result<internalExpressionValue, string> => {
2022-05-24 21:02:27 +00:00
switch FunctionRegistry_Helpers.Prepare.ToValueArray.Record.twoArgs([e]) {
| Ok([FRValueLambda(lambda), FRValueArray(inputs)]) => {
2022-05-24 11:52:27 +00:00
open FunctionRegistry_Helpers.Prepare
2022-05-24 21:02:27 +00:00
let getMinMax = arg =>
2022-05-24 11:52:27 +00:00
ToValueArray.Record.toArgs([arg])
->E.R.bind(ToValueTuple.twoNumbers)
2022-05-24 21:02:27 +00:00
->E.R2.fmap(((min, max)) => Declaration.ContinuousFloatArg.make(min, max))
2022-05-24 11:52:27 +00:00
inputs
->E.A2.fmap(getMinMax)
->E.A.R.firstErrorOrOpen
2022-06-23 18:38:07 +00:00
->E.R2.fmap(args => ReducerInterface_InternalExpressionValue.IEvDeclaration(
Declaration.make(lambda, args),
2022-05-24 21:02:27 +00:00
))
2022-05-24 11:52:27 +00:00
}
2022-05-27 11:29:39 +00:00
| Error(r) => Error(r)
| Ok(_) => Error(FunctionRegistry_Helpers.impossibleError)
2022-05-24 11:52:27 +00:00
}
}
}
2022-07-14 20:31:48 +00:00
module PointSet = {
2022-07-15 00:21:07 +00:00
let nameSpace = "PointSet"
2022-07-14 20:31:48 +00:00
let requiresNamespace = true
let inputsTodist = (inputs: array<FunctionRegistry_Core.frValue>, makeDist) => {
let array = inputs->getOrError(0)->E.R.bind(Prepare.ToValueArray.Array.openA)
let xyCoords =
array->E.R.bind(xyCoords =>
xyCoords
->E.A2.fmap(xyCoord =>
[xyCoord]->Prepare.ToValueArray.Record.twoArgs->E.R.bind(Prepare.ToValueTuple.twoNumbers)
)
->E.A.R.firstErrorOrOpen
)
let expressionValue =
xyCoords
->E.R.bind(r => r->XYShape.T.makeFromZipped->E.R2.errMap(XYShape.Error.toString))
->E.R2.fmap(r => ReducerInterface_InternalExpressionValue.IEvDistribution(
PointSet(makeDist(r)),
))
expressionValue
}
2022-07-14 20:31:48 +00:00
let library = [
Function.make(
~name="PointSet.makeContinuous",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[
FnDefinition.make(
~requiresNamespace,
~name="makeContinuous",
~inputs=[FRTypeArray(FRTypeRecord([("x", FRTypeNumeric), ("y", FRTypeNumeric)]))],
~run=(_, inputs, _) => inputsTodist(inputs, r => Continuous(Continuous.make(r))),
2022-07-14 20:31:48 +00:00
(),
),
],
(),
),
Function.make(
~name="PointSet.makeDiscrete",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[
FnDefinition.make(
~requiresNamespace,
~name="makeDiscrete",
~inputs=[FRTypeArray(FRTypeRecord([("x", FRTypeNumeric), ("y", FRTypeNumeric)]))],
~run=(_, inputs, _) => inputsTodist(inputs, r => Discrete(Discrete.make(r))),
2022-07-14 20:31:48 +00:00
(),
),
],
(),
),
]
}
module Functionn = {
2022-07-15 00:21:07 +00:00
let nameSpace = "Function"
2022-07-14 20:31:48 +00:00
let library = [
Function.make(
~name="Function.declare",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 23:13:22 +00:00
~description="Adds metadata to a function of the input ranges. Works now for numeric and date inputs. This is useful when making predictions. It allows you to limit the domain that your prediction will be used and scored within.",
~examples=[
`declareFn({
2022-07-14 23:13:22 +00:00
fn: {|a,b| a },
inputs: [
{min: 0, max: 100},
{min: 30, max: 50}
]
})`,
],
2022-07-14 23:13:22 +00:00
~isExperimental=true,
2022-07-14 20:31:48 +00:00
~definitions=[
FnDefinition.make(
~requiresNamespace=true,
~name="declare",
~inputs=[Declaration.frType],
~run=(_, inputs, _) => {
2022-07-14 20:31:48 +00:00
inputs->getOrError(0)->E.R.bind(Declaration.fromExpressionValue)
},
(),
),
],
(),
),
]
}
module DistributionCreation = {
2022-07-15 00:21:07 +00:00
let nameSpace = "Dist"
2022-07-14 20:31:48 +00:00
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) => {
2022-05-27 17:37:37 +00:00
FnDefinition.make(
2022-07-14 20:31:48 +00:00
~requiresNamespace=false,
~name,
~inputs=[FRTypeDistOrNumber, FRTypeDistOrNumber],
~run=(_, inputs, env) => inputs->Prepare.ToValueTuple.twoDistOrNumber->process(~fn, ~env),
(),
2022-07-14 20:31:48 +00:00
)
}
let makeRecordP5P95 = (name, fn) => {
2022-05-27 18:03:41 +00:00
FnDefinition.make(
2022-07-14 20:31:48 +00:00
~requiresNamespace=false,
~name,
~inputs=[FRTypeRecord([("p5", FRTypeDistOrNumber), ("p95", FRTypeDistOrNumber)])],
~run=(_, inputs, env) =>
2022-07-14 20:31:48 +00:00
inputs->Prepare.ToValueTuple.Record.twoDistOrNumber->process(~fn, ~env),
(),
2022-07-14 20:31:48 +00:00
)
}
let makeRecordMeanStdev = (name, fn) => {
FnDefinition.make(
2022-07-14 20:31:48 +00:00
~name,
~requiresNamespace=false,
~inputs=[FRTypeRecord([("mean", FRTypeDistOrNumber), ("stdev", FRTypeDistOrNumber)])],
~run=(_, inputs, env) =>
2022-07-14 20:31:48 +00:00
inputs->Prepare.ToValueTuple.Record.twoDistOrNumber->process(~fn, ~env),
(),
2022-07-14 20:31:48 +00:00
)
}
}
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(
~requiresNamespace=false,
~name,
~inputs=[FRTypeDistOrNumber],
~run=(_, inputs, env) => inputs->Prepare.ToValueTuple.oneDistOrNumber->process(~fn, ~env),
2022-07-14 20:31:48 +00:00
(),
)
}
2022-07-14 20:31:48 +00:00
let library = [
Function.make(
~name="Normal",
2022-07-15 00:21:07 +00:00
~nameSpace,
~examples=["normal(5,1)", "normal({p5: 4, p95: 10})", "normal({mean: 5, stdev: 2})"],
2022-07-14 20:31:48 +00:00
~definitions=[
TwoArgDist.make("normal", twoArgs(SymbolicDist.Normal.make)),
2022-07-14 23:13:22 +00:00
TwoArgDist.makeRecordP5P95("normal", r =>
twoArgs(SymbolicDist.Normal.from90PercentCI, r)->Ok
),
TwoArgDist.makeRecordMeanStdev("normal", twoArgs(SymbolicDist.Normal.make)),
2022-07-14 20:31:48 +00:00
],
(),
),
Function.make(
~name="Lognormal",
2022-07-15 00:21:07 +00:00
~nameSpace,
~examples=[
"lognormal(0.5, 0.8)",
"lognormal({p5: 4, p95: 10})",
2022-07-15 00:21:07 +00:00
"lognormal({mean: 5, stdev: 2})",
],
2022-07-14 20:31:48 +00:00
~definitions=[
TwoArgDist.make("lognormal", twoArgs(SymbolicDist.Lognormal.make)),
TwoArgDist.makeRecordP5P95("lognormal", r =>
twoArgs(SymbolicDist.Lognormal.from90PercentCI, r)->Ok
),
TwoArgDist.makeRecordMeanStdev(
"lognormal",
twoArgs(SymbolicDist.Lognormal.fromMeanAndStdev),
),
],
(),
),
Function.make(
~name="Uniform",
2022-07-15 00:21:07 +00:00
~nameSpace,
~examples=[`uniform(10, 12)`],
2022-07-14 20:31:48 +00:00
~definitions=[TwoArgDist.make("uniform", twoArgs(SymbolicDist.Uniform.make))],
(),
),
Function.make(
~name="Beta",
2022-07-15 00:21:07 +00:00
~nameSpace,
~examples=[`beta(20, 25)`, `beta({mean: 0.39, stdev: 0.1})`],
2022-07-14 20:31:48 +00:00
~definitions=[
TwoArgDist.make("beta", twoArgs(SymbolicDist.Beta.make)),
TwoArgDist.makeRecordMeanStdev("beta", twoArgs(SymbolicDist.Beta.fromMeanAndStdev)),
],
(),
),
Function.make(
~name="Cauchy",
2022-07-15 00:21:07 +00:00
~nameSpace,
~examples=[`cauchy(5, 1)`],
2022-07-14 20:31:48 +00:00
~definitions=[TwoArgDist.make("cauchy", twoArgs(SymbolicDist.Cauchy.make))],
(),
),
Function.make(
~name="Gamma",
2022-07-15 00:21:07 +00:00
~nameSpace,
~examples=[`gamma(5, 1)`],
2022-07-14 20:31:48 +00:00
~definitions=[TwoArgDist.make("gamma", twoArgs(SymbolicDist.Gamma.make))],
(),
),
Function.make(
~name="Logistic",
2022-07-15 00:21:07 +00:00
~nameSpace,
~examples=[`logistic(5, 1)`],
2022-07-14 20:31:48 +00:00
~definitions=[TwoArgDist.make("logistic", twoArgs(SymbolicDist.Logistic.make))],
(),
),
Function.make(
~name="To (Distribution)",
2022-07-15 00:21:07 +00:00
~nameSpace,
~examples=[`5 to 10`, `to(5,10)`, `-5 to 5`],
2022-07-14 20:31:48 +00:00
~definitions=[
TwoArgDist.make("to", twoArgs(SymbolicDist.From90thPercentile.make)),
TwoArgDist.make(
"credibleIntervalToDistribution",
twoArgs(SymbolicDist.From90thPercentile.make),
),
],
(),
),
Function.make(
~name="Exponential",
2022-07-15 00:21:07 +00:00
~nameSpace,
~examples=[`exponential(2)`],
2022-07-14 20:31:48 +00:00
~definitions=[OneArgDist.make("exponential", SymbolicDist.Exponential.make)],
(),
),
Function.make(
~name="Bernoulli",
2022-07-15 00:21:07 +00:00
~nameSpace,
~examples=[`bernoulli(0.5)`],
2022-07-14 20:31:48 +00:00
~definitions=[OneArgDist.make("bernoulli", SymbolicDist.Bernoulli.make)],
(),
),
Function.make(
~name="PointMass",
2022-07-15 00:21:07 +00:00
~nameSpace,
~examples=[`pointMass(0.5)`],
2022-07-14 20:31:48 +00:00
~definitions=[OneArgDist.make("pointMass", SymbolicDist.Float.makeSafe)],
(),
),
]
}
module Number = {
2022-07-15 00:21:07 +00:00
let nameSpace = "Number"
2022-07-14 20:31:48 +00:00
let requiresNamespace = false
module NumberToNumber = {
let make = (name, fn) =>
2022-06-08 05:35:40 +00:00
FnDefinition.make(
2022-07-14 20:31:48 +00:00
~requiresNamespace,
~name,
~inputs=[FRTypeNumber],
~run=(_, inputs, _) => {
2022-07-14 20:31:48 +00:00
inputs
->getOrError(0)
->E.R.bind(Prepare.oneNumber)
->E.R2.fmap(fn)
->E.R2.fmap(Wrappers.evNumber)
2022-06-08 05:35:40 +00:00
},
(),
2022-07-14 20:31:48 +00:00
)
}
module ArrayNumberDist = {
let make = (name, fn) => {
FnDefinition.make(
2022-07-14 20:31:48 +00:00
~requiresNamespace=false,
~name,
~inputs=[FRTypeArray(FRTypeNumber)],
~run=(_, inputs, _) =>
2022-07-14 20:31:48 +00:00
Prepare.ToTypedArray.numbers(inputs)
->E.R.bind(r => E.A.length(r) === 0 ? Error("List is empty") : Ok(r))
->E.R.bind(fn),
(),
2022-07-14 20:31:48 +00:00
)
}
let make2 = (name, fn) => {
FnDefinition.make(
2022-07-14 20:31:48 +00:00
~name,
~inputs=[FRTypeArray(FRTypeAny)],
~run=(_, inputs, _) =>
2022-07-14 20:31:48 +00:00
Prepare.ToTypedArray.numbers(inputs)
->E.R.bind(r => E.A.length(r) === 0 ? Error("List is empty") : Ok(r))
->E.R.bind(fn),
(),
2022-07-14 20:31:48 +00:00
)
}
}
let library = [
Function.make(
~name="Floor",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[NumberToNumber.make("floor", Js.Math.floor_float)],
(),
),
Function.make(
~name="Ceiling",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[NumberToNumber.make("ceil", Js.Math.ceil_float)],
(),
),
Function.make(
~name="Absolute Value",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[NumberToNumber.make("abs", Js.Math.abs_float)],
(),
),
2022-07-15 00:21:07 +00:00
Function.make(
~name="Exponent",
~nameSpace,
~definitions=[NumberToNumber.make("exp", Js.Math.exp)],
(),
),
Function.make(
~name="Log",
~nameSpace,
~definitions=[NumberToNumber.make("log", Js.Math.log)],
(),
),
2022-07-14 20:31:48 +00:00
Function.make(
~name="Log Base 10",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[NumberToNumber.make("log10", Js.Math.log10)],
(),
),
2022-07-15 00:21:07 +00:00
Function.make(
~name="Log Base 2",
~nameSpace,
~definitions=[NumberToNumber.make("log2", Js.Math.log2)],
(),
),
Function.make(
~name="Round",
~nameSpace,
~definitions=[NumberToNumber.make("round", Js.Math.round)],
(),
),
2022-07-14 20:31:48 +00:00
Function.make(
~name="Sum",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[ArrayNumberDist.make("sum", r => r->E.A.Floats.sum->Wrappers.evNumber->Ok)],
(),
),
Function.make(
~name="Product",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[
ArrayNumberDist.make("product", r => r->E.A.Floats.product->Wrappers.evNumber->Ok),
],
(),
),
Function.make(
~name="Min",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[ArrayNumberDist.make("min", r => r->E.A.Floats.min->Wrappers.evNumber->Ok)],
(),
),
Function.make(
~name="Max",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[ArrayNumberDist.make("max", r => r->E.A.Floats.max->Wrappers.evNumber->Ok)],
(),
),
Function.make(
~name="Mean",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[ArrayNumberDist.make("mean", r => r->E.A.Floats.mean->Wrappers.evNumber->Ok)],
(),
),
Function.make(
~name="Geometric Mean",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[
ArrayNumberDist.make("geomean", r => r->E.A.Floats.geomean->Wrappers.evNumber->Ok),
],
(),
),
Function.make(
~name="Standard Deviation",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[ArrayNumberDist.make("stdev", r => r->E.A.Floats.stdev->Wrappers.evNumber->Ok)],
(),
),
Function.make(
~name="Variance",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[
ArrayNumberDist.make("variance", r => r->E.A.Floats.stdev->Wrappers.evNumber->Ok),
],
(),
),
Function.make(
~name="Sort",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[
ArrayNumberDist.make("sort", r =>
r->E.A.Floats.sort->E.A2.fmap(Wrappers.evNumber)->Wrappers.evArray->Ok
),
],
(),
),
Function.make(
~name="Cumulative Sum",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[
ArrayNumberDist.make("cumsum", r =>
r->E.A.Floats.cumsum->E.A2.fmap(Wrappers.evNumber)->Wrappers.evArray->Ok
),
],
(),
),
Function.make(
~name="Cumulative Prod",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[
ArrayNumberDist.make("cumprod", r =>
r->E.A.Floats.cumsum->E.A2.fmap(Wrappers.evNumber)->Wrappers.evArray->Ok
),
],
(),
),
Function.make(
~name="Diff",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[
ArrayNumberDist.make("diff", r =>
r->E.A.Floats.diff->E.A2.fmap(Wrappers.evNumber)->Wrappers.evArray->Ok
),
],
(),
),
]
}
module Dict = {
2022-07-15 00:21:07 +00:00
let nameSpace = "Dict"
module Internals = {
type t = ReducerInterface_InternalExpressionValue.map
let keys = (a: t): internalExpressionValue => IEvArray(
Belt.Map.String.keysToArray(a)->E.A2.fmap(Wrappers.evString),
)
let values = (a: t): internalExpressionValue => IEvArray(Belt.Map.String.valuesToArray(a))
let toList = (a: t): internalExpressionValue =>
Belt.Map.String.toArray(a)
->E.A2.fmap(((key, value)) => Wrappers.evArray([IEvString(key), value]))
->Wrappers.evArray
let fromList = (items: array<internalExpressionValue>): result<
internalExpressionValue,
string,
> =>
items
->E.A2.fmap(item => {
switch (item: internalExpressionValue) {
| IEvArray([IEvString(string), value]) => (string, value)->Ok
| _ => Error(impossibleError)
}
})
->E.A.R.firstErrorOrOpen
->E.R2.fmap(Belt.Map.String.fromArray)
->E.R2.fmap(Wrappers.evRecord)
let merge = (a: t, b: t): internalExpressionValue => 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.
let mergeMany = (a: array<t>): internalExpressionValue => {
let mergedValues =
a->E.A2.fmap(Belt.Map.String.toArray)->Belt.Array.concatMany->Belt.Map.String.fromArray
IEvRecord(mergedValues)
}
}
2022-07-14 20:31:48 +00:00
let library = [
Function.make(
~name="merge",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[
FnDefinition.make(
~requiresNamespace=true,
~name="merge",
~inputs=[FRTypeDict(FRTypeAny), FRTypeDict(FRTypeAny)],
~run=(inputs, _, _) => {
2022-07-14 20:31:48 +00:00
switch inputs {
| [IEvRecord(d1), IEvRecord(d2)] => Internals.merge(d1, d2)->Ok
2022-07-14 20:31:48 +00:00
| _ => Error(impossibleError)
}
},
2022-07-14 20:31:48 +00:00
(),
),
],
(),
),
//TODO: Change to use new mergeMany() function.
2022-07-14 20:31:48 +00:00
Function.make(
~name="mergeMany",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[
FnDefinition.make(
~requiresNamespace=true,
~name="mergeMany",
~inputs=[FRTypeArray(FRTypeDict(FRTypeAny))],
~run=(_, inputs, _) =>
2022-07-14 20:31:48 +00:00
inputs
->Prepare.ToTypedArray.dicts
->E.R2.fmap(E.Dict.concatMany)
->E.R2.fmap(Js.Dict.map((. r) => FunctionRegistry_Core.FRType.matchReverse(r)))
->E.R2.fmap(r => r->Js.Dict.entries->Belt.Map.String.fromArray)
->E.R2.fmap(Wrappers.evRecord),
(),
),
],
(),
),
Function.make(
~name="keys",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[
FnDefinition.make(
~requiresNamespace=true,
~name="keys",
~inputs=[FRTypeDict(FRTypeAny)],
~run=(inputs, _, _) =>
2022-07-14 20:31:48 +00:00
switch inputs {
| [IEvRecord(d1)] => Internals.keys(d1)->Ok
2022-07-14 20:31:48 +00:00
| _ => Error(impossibleError)
},
(),
),
],
(),
),
Function.make(
~name="values",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[
FnDefinition.make(
~requiresNamespace=true,
~name="values",
~inputs=[FRTypeDict(FRTypeAny)],
~run=(inputs, _, _) =>
2022-07-14 20:31:48 +00:00
switch inputs {
| [IEvRecord(d1)] => Internals.values(d1)->Ok
2022-07-14 20:31:48 +00:00
| _ => Error(impossibleError)
},
(),
),
],
(),
),
Function.make(
~name="toList",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[
FnDefinition.make(
~requiresNamespace=true,
~name="toList",
~inputs=[FRTypeDict(FRTypeAny)],
~run=(inputs, _, _) =>
2022-07-14 20:31:48 +00:00
switch inputs {
| [IEvRecord(dict)] => dict->Internals.toList->Ok
2022-07-14 20:31:48 +00:00
| _ => Error(impossibleError)
},
(),
),
],
(),
),
Function.make(
~name="fromList",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[
FnDefinition.make(
~requiresNamespace=true,
~name="fromList",
~inputs=[FRTypeArray(FRTypeArray(FRTypeAny))],
~run=(inputs, _, _) =>
switch inputs {
| [IEvArray(items)] => Internals.fromList(items)
| _ => Error(impossibleError)
},
2022-07-14 20:31:48 +00:00
(),
),
],
(),
),
]
}
2022-07-14 20:31:48 +00:00
module List = {
2022-07-15 00:21:07 +00:00
let nameSpace = "List"
2022-07-14 20:31:48 +00:00
let requiresNamespace = true
module Internals = {
let makeFromNumber = (
n: float,
value: internalExpressionValue,
): internalExpressionValue => IEvArray(Belt.Array.make(E.Float.toInt(n), value))
let upTo = (low: float, high: float): internalExpressionValue => IEvArray(
E.A.Floats.range(low, high, (high -. low +. 1.0)->E.Float.toInt)->E.A2.fmap(
Wrappers.evNumber,
),
)
let first = (v: array<internalExpressionValue>): result<internalExpressionValue, string> =>
v->E.A.first |> E.O.toResult("No first element")
let last = (v: array<internalExpressionValue>): result<internalExpressionValue, string> =>
v->E.A.last |> E.O.toResult("No last element")
let reverse = (array: array<internalExpressionValue>): internalExpressionValue => IEvArray(
Belt.Array.reverse(array),
)
}
2022-07-14 20:31:48 +00:00
let library = [
Function.make(
~name="List.make",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[
//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(
~requiresNamespace,
~name="make",
~inputs=[FRTypeNumber, FRTypeAny],
~run=(inputs, _, _) => {
2022-07-14 20:31:48 +00:00
switch inputs {
| [IEvNumber(number), value] => Internals.makeFromNumber(number, value)->Ok
2022-07-14 20:31:48 +00:00
| _ => Error(impossibleError)
}
},
(),
),
],
(),
),
Function.make(
~name="List.upTo",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[
FnDefinition.make(
~requiresNamespace,
~name="upTo",
~inputs=[FRTypeNumber, FRTypeNumber],
~run=(_, inputs, _) =>
2022-07-14 20:31:48 +00:00
inputs
->Prepare.ToValueTuple.twoNumbers
->E.R2.fmap(((low, high)) => Internals.upTo(low, high)),
2022-07-14 20:31:48 +00:00
(),
),
],
(),
),
Function.make(
~name="List.first",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[
FnDefinition.make(
~requiresNamespace,
~name="first",
~inputs=[FRTypeArray(FRTypeAny)],
~run=(inputs, _, _) =>
2022-07-14 20:31:48 +00:00
switch inputs {
| [IEvArray(array)] => Internals.first(array)
2022-07-14 20:31:48 +00:00
| _ => Error(impossibleError)
},
(),
),
],
(),
),
Function.make(
~name="List.last",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[
FnDefinition.make(
~requiresNamespace=false,
~name="last",
~inputs=[FRTypeArray(FRTypeAny)],
~run=(inputs, _, _) =>
2022-07-14 20:31:48 +00:00
switch inputs {
| [IEvArray(array)] => Internals.last(array)
2022-07-14 20:31:48 +00:00
| _ => Error(impossibleError)
},
(),
),
],
(),
),
Function.make(
~name="List.reverse",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[
FnDefinition.make(
~requiresNamespace=false,
~name="reverse",
2022-07-14 20:31:48 +00:00
~inputs=[FRTypeArray(FRTypeAny)],
~run=(inputs, _, _) =>
2022-07-14 20:31:48 +00:00
switch inputs {
| [IEvArray(array)] => Internals.reverse(array)->Ok
2022-07-14 20:31:48 +00:00
| _ => Error(impossibleError)
},
(),
),
],
(),
),
]
}
2022-07-14 20:31:48 +00:00
module Scoring = {
2022-07-15 00:21:07 +00:00
let nameSpace = "Dist"
2022-07-14 20:31:48 +00:00
let requiresNamespace = false
let runScoring = (estimate, answer, prior, env) => {
GenericDist.Score.logScore(~estimate, ~answer, ~prior, ~env)
->E.R2.fmap(FunctionRegistry_Helpers.Wrappers.evNumber)
->E.R2.errMap(DistributionTypes.Error.toString)
}
let library = [
Function.make(
~name="logScore",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[
FnDefinition.make(
~requiresNamespace,
~name="logScore",
~inputs=[
FRTypeRecord([
("estimate", FRTypeDist),
("answer", FRTypeDistOrNumber),
("prior", FRTypeDist),
]),
],
~run=(_, inputs, env) => {
2022-07-14 20:31:48 +00:00
switch FunctionRegistry_Helpers.Prepare.ToValueArray.Record.threeArgs(inputs) {
| Ok([
FRValueDist(estimate),
FRValueDistOrNumber(FRValueDist(d)),
FRValueDist(prior),
]) =>
runScoring(estimate, Score_Dist(d), Some(prior), env)
| Ok([
FRValueDist(estimate),
FRValueDistOrNumber(FRValueNumber(d)),
FRValueDist(prior),
]) =>
runScoring(estimate, Score_Scalar(d), Some(prior), env)
| Error(e) => Error(e)
| _ => Error(FunctionRegistry_Helpers.impossibleError)
}
},
(),
),
FnDefinition.make(
~name="logScore",
~requiresNamespace,
~inputs=[FRTypeRecord([("estimate", FRTypeDist), ("answer", FRTypeDistOrNumber)])],
~run=(_, inputs, env) => {
2022-07-14 20:31:48 +00:00
switch FunctionRegistry_Helpers.Prepare.ToValueArray.Record.twoArgs(inputs) {
| Ok([FRValueDist(estimate), FRValueDistOrNumber(FRValueDist(d))]) =>
runScoring(estimate, Score_Dist(d), None, env)
| Ok([FRValueDist(estimate), FRValueDistOrNumber(FRValueNumber(d))]) =>
runScoring(estimate, Score_Scalar(d), None, env)
| Error(e) => Error(e)
| _ => Error(FunctionRegistry_Helpers.impossibleError)
}
},
(),
),
],
(),
),
Function.make(
~name="klDivergence",
2022-07-15 00:21:07 +00:00
~nameSpace,
2022-07-14 20:31:48 +00:00
~definitions=[
FnDefinition.make(
~name="klDivergence",
~requiresNamespace,
~inputs=[FRTypeDist, FRTypeDist],
~run=(_, inputs, env) => {
2022-07-14 20:31:48 +00:00
switch inputs {
| [FRValueDist(estimate), FRValueDist(d)] =>
runScoring(estimate, Score_Dist(d), None, env)
| _ => Error(FunctionRegistry_Helpers.impossibleError)
}
},
(),
),
],
(),
),
]
}
2022-07-14 20:31:48 +00:00
let registry = Belt.Array.concatMany([
PointSet.library,
Functionn.library,
Number.library,
Dict.library,
List.library,
DistributionCreation.library,
Scoring.library,
])