Renamed itype->frType, value-> frValue
This commit is contained in:
parent
c9d6302cbf
commit
390ac2e2bb
|
@ -1,43 +1,39 @@
|
||||||
type expressionValue = ReducerInterface_ExpressionValue.expressionValue
|
type expressionValue = ReducerInterface_ExpressionValue.expressionValue
|
||||||
|
|
||||||
type rec itype =
|
/*
|
||||||
| I_Number
|
Function Registry "Type". A type, without any other information.
|
||||||
| I_Numeric
|
Like, #Float
|
||||||
| I_DistOrNumber
|
*/
|
||||||
| I_Record(iRecord)
|
type rec frType =
|
||||||
| I_Array(array<itype>)
|
| FRTypeNumber
|
||||||
| I_Option(itype)
|
| FRTypeNumeric
|
||||||
and iRecord = array<iRecordParam>
|
| FRTypeDistOrNumber
|
||||||
and iRecordParam = (string, itype)
|
| FRTypeRecord(frTypeRecord)
|
||||||
|
| FRTypeArray(array<frType>)
|
||||||
|
| FRTypeOption(frType)
|
||||||
|
and frTypeRecord = array<frTypeRecordParam>
|
||||||
|
and frTypeRecordParam = (string, frType)
|
||||||
|
|
||||||
module Itype = {
|
/*
|
||||||
let rec toString = (t: itype) =>
|
Function Registry "Value". A type, with the information of that type.
|
||||||
switch t {
|
Like, #Float(40.0)
|
||||||
| I_Number => "number"
|
*/
|
||||||
| I_Numeric => "numeric"
|
type rec frValue =
|
||||||
| I_DistOrNumber => "distOrNumber"
|
| FRValueNumber(float)
|
||||||
| I_Record(r) => {
|
| FRValueDist(DistributionTypes.genericDist)
|
||||||
let input = ((name, itype): iRecordParam) => `${name}: ${toString(itype)}`
|
| FRValueOption(option<frValue>)
|
||||||
`record({${r->E.A2.fmap(input)->E.A2.joinWith(", ")}})`
|
| FRValueDistOrNumber(frValueDistOrNumber)
|
||||||
}
|
| FRValueRecord(frValueRecord)
|
||||||
| I_Array(r) => `record(${r->E.A2.fmap(toString)->E.A2.joinWith(", ")})`
|
and frValueRecord = array<frValueRecordParam>
|
||||||
| I_Option(v) => `option(${toString(v)})`
|
and frValueRecordParam = (string, frValue)
|
||||||
}
|
and frValueDistOrNumber = FRValueNumber(float) | FRValueDist(DistributionTypes.genericDist)
|
||||||
|
|
||||||
|
type fnDefinition = {
|
||||||
|
name: string,
|
||||||
|
inputs: array<frType>,
|
||||||
|
run: array<frValue> => result<expressionValue, string>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type rec value =
|
|
||||||
| Number(float)
|
|
||||||
| Dist(DistributionTypes.genericDist)
|
|
||||||
| Option(option<value>)
|
|
||||||
| DistOrNumber(distOrNumber)
|
|
||||||
| Record(record)
|
|
||||||
and record = array<(string, value)>
|
|
||||||
and distOrNumber = Number(float) | Dist(DistributionTypes.genericDist)
|
|
||||||
|
|
||||||
type runFn = array<value> => result<expressionValue, string>
|
|
||||||
|
|
||||||
type fnDefinition = {name: string, inputs: array<itype>, run: runFn}
|
|
||||||
|
|
||||||
type function = {
|
type function = {
|
||||||
name: string,
|
name: string,
|
||||||
definitions: array<fnDefinition>,
|
definitions: array<fnDefinition>,
|
||||||
|
@ -45,31 +41,58 @@ type function = {
|
||||||
|
|
||||||
type registry = array<function>
|
type registry = array<function>
|
||||||
|
|
||||||
let rec matchInput = (input: itype, r: expressionValue): option<value> =>
|
module FRType = {
|
||||||
switch (input, r) {
|
type t = frType
|
||||||
| (I_Number, EvNumber(f)) => Some(Number(f))
|
let rec toString = (t: t) =>
|
||||||
| (I_DistOrNumber, EvNumber(f)) => Some(DistOrNumber(Number(f)))
|
switch t {
|
||||||
| (I_DistOrNumber, EvDistribution(Symbolic(#Float(f)))) => Some(DistOrNumber(Number(f)))
|
| FRTypeNumber => "number"
|
||||||
| (I_DistOrNumber, EvDistribution(f)) => Some(DistOrNumber(Dist(f)))
|
| FRTypeNumeric => "numeric"
|
||||||
| (I_Numeric, EvNumber(f)) => Some(Number(f))
|
| FRTypeDistOrNumber => "frValueDistOrNumber"
|
||||||
| (I_Numeric, EvDistribution(Symbolic(#Float(f)))) => Some(Number(f))
|
| FRTypeRecord(r) => {
|
||||||
| (I_Option(v), _) => Some(Option(matchInput(v, r)))
|
let input = ((name, frType): frTypeRecordParam) => `${name}: ${toString(frType)}`
|
||||||
| (I_Record(recordParams), EvRecord(record)) => {
|
`record({${r->E.A2.fmap(input)->E.A2.joinWith(", ")}})`
|
||||||
let getAndMatch = (name, input) =>
|
|
||||||
E.Dict.get(record, name)->E.O.bind(v => matchInput(input, v))
|
|
||||||
let arrayOfNameValues: array<(Js.Dict.key, option<value>)> =
|
|
||||||
recordParams->E.A2.fmap(((name, input)) => (name, getAndMatch(name, input)))
|
|
||||||
let hasNullValues = E.A.hasBy(arrayOfNameValues, ((_, value)) => E.O.isNone(value))
|
|
||||||
if hasNullValues {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
arrayOfNameValues
|
|
||||||
->E.A2.fmap(((name, value)) => (name, value->E.O2.toExn("")))
|
|
||||||
->(r => Some(Record(r)))
|
|
||||||
}
|
}
|
||||||
|
| FRTypeArray(r) => `record(${r->E.A2.fmap(toString)->E.A2.joinWith(", ")})`
|
||||||
|
| FRTypeOption(v) => `option(${toString(v)})`
|
||||||
|
}
|
||||||
|
|
||||||
|
let rec matchWithExpressionValue = (input: t, r: expressionValue): option<frValue> =>
|
||||||
|
switch (input, r) {
|
||||||
|
| (FRTypeNumber, EvNumber(f)) => Some(FRValueNumber(f))
|
||||||
|
| (FRTypeDistOrNumber, EvNumber(f)) => Some(FRValueDistOrNumber(FRValueNumber(f)))
|
||||||
|
| (FRTypeDistOrNumber, EvDistribution(Symbolic(#Float(f)))) =>
|
||||||
|
Some(FRValueDistOrNumber(FRValueNumber(f)))
|
||||||
|
| (FRTypeDistOrNumber, EvDistribution(f)) => Some(FRValueDistOrNumber(FRValueDist(f)))
|
||||||
|
| (FRTypeNumeric, EvNumber(f)) => Some(FRValueNumber(f))
|
||||||
|
| (FRTypeNumeric, EvDistribution(Symbolic(#Float(f)))) => Some(FRValueNumber(f))
|
||||||
|
| (FRTypeOption(v), _) => Some(FRValueOption(matchWithExpressionValue(v, r)))
|
||||||
|
| (FRTypeRecord(recordParams), EvRecord(record)) => {
|
||||||
|
let getAndMatch = (name, input) =>
|
||||||
|
E.Dict.get(record, name)->E.O.bind(matchWithExpressionValue(input))
|
||||||
|
//All names in the type must be present. If any are missing, the corresponding
|
||||||
|
//value will be None, and this function would return None.
|
||||||
|
let namesAndValues: array<option<(Js.Dict.key, frValue)>> =
|
||||||
|
recordParams->E.A2.fmap(((name, input)) =>
|
||||||
|
getAndMatch(name, input)->E.O2.fmap(match => (name, match))
|
||||||
|
)
|
||||||
|
namesAndValues->E.A.O.openIfAllSome->E.O2.fmap(r => FRValueRecord(r))
|
||||||
|
}
|
||||||
|
| _ => None
|
||||||
|
}
|
||||||
|
|
||||||
|
let matchWithExpressionValueArray = (inputs: array<t>, args: array<expressionValue>): option<
|
||||||
|
array<frValue>,
|
||||||
|
> => {
|
||||||
|
let isSameLength = E.A.length(inputs) == E.A.length(args)
|
||||||
|
if !isSameLength {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
E.A.zip(inputs, args)
|
||||||
|
->E.A2.fmap(((input, arg)) => matchWithExpressionValue(input, arg))
|
||||||
|
->E.A.O.openIfAllSome
|
||||||
}
|
}
|
||||||
| _ => None
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module Matcher = {
|
module Matcher = {
|
||||||
module MatchSimple = {
|
module MatchSimple = {
|
||||||
|
@ -107,19 +130,8 @@ module Matcher = {
|
||||||
module FnDefinition = {
|
module FnDefinition = {
|
||||||
type definitionMatch = MatchSimple.t
|
type definitionMatch = MatchSimple.t
|
||||||
|
|
||||||
let getArgValues = (f: fnDefinition, args: array<expressionValue>): option<array<value>> => {
|
|
||||||
let mainInputTypes = f.inputs
|
|
||||||
if E.A.length(f.inputs) !== E.A.length(args) {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
E.A.zip(mainInputTypes, args)
|
|
||||||
->E.A2.fmap(((input, arg)) => matchInput(input, arg))
|
|
||||||
->E.A.O.openIfAllSome
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let matchAssumingSameName = (f: fnDefinition, args: array<expressionValue>) => {
|
let matchAssumingSameName = (f: fnDefinition, args: array<expressionValue>) => {
|
||||||
switch getArgValues(f, args) {
|
switch FRType.matchWithExpressionValueArray(f.inputs, args) {
|
||||||
| Some(_) => MatchSimple.FullMatch
|
| Some(_) => MatchSimple.FullMatch
|
||||||
| None => MatchSimple.SameNameDifferentArguments
|
| None => MatchSimple.SameNameDifferentArguments
|
||||||
}
|
}
|
||||||
|
@ -228,43 +240,37 @@ module Matcher = {
|
||||||
|
|
||||||
module FnDefinition = {
|
module FnDefinition = {
|
||||||
type t = fnDefinition
|
type t = fnDefinition
|
||||||
let getArgValues = (t: t, args: array<expressionValue>): option<array<value>> => {
|
|
||||||
let mainInputTypes = t.inputs
|
|
||||||
if E.A.length(t.inputs) !== E.A.length(args) {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
E.A.zip(mainInputTypes, args)
|
|
||||||
->E.A2.fmap(((input, arg)) => matchInput(input, arg))
|
|
||||||
->E.A.O.openIfAllSome
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let defToString = (t: t) => t.inputs->E.A2.fmap(Itype.toString)->E.A2.joinWith(", ")
|
let defToString = (t: t) => t.inputs->E.A2.fmap(FRType.toString)->E.A2.joinWith(", ")
|
||||||
|
|
||||||
let run = (t: t, args: array<expressionValue>) => {
|
let run = (t: t, args: array<expressionValue>) => {
|
||||||
let argValues = getArgValues(t, args)
|
let argValues = FRType.matchWithExpressionValueArray(t.inputs, args)
|
||||||
switch argValues {
|
switch argValues {
|
||||||
| Some(values) => t.run(values)
|
| Some(values) => t.run(values)
|
||||||
| None => Error("Impossible")
|
| None => Error("Incorrect Types")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
module Function = {
|
let make = (~name, ~inputs, ~run): fnDefinition => {
|
||||||
type definitionId = int
|
|
||||||
let make = (~name, ~definitions): function => {
|
|
||||||
name: name,
|
|
||||||
definitions: definitions,
|
|
||||||
}
|
|
||||||
|
|
||||||
let makeDefinition = (~name, ~inputs, ~run): fnDefinition => {
|
|
||||||
name: name,
|
name: name,
|
||||||
inputs: inputs,
|
inputs: inputs,
|
||||||
run: run,
|
run: run,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module Function = {
|
||||||
|
let make = (~name, ~definitions): function => {
|
||||||
|
name: name,
|
||||||
|
definitions: definitions,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module Registry = {
|
module Registry = {
|
||||||
|
/*
|
||||||
|
There's a (potential+minor) bug here: If a function definition is called outside of the calls
|
||||||
|
to the registry, then it's possible that there could be a match after the registry is
|
||||||
|
called. However, for now, we could just call the registry last.
|
||||||
|
*/
|
||||||
let matchAndRun = (r: registry, fnName: string, args: array<expressionValue>) => {
|
let matchAndRun = (r: registry, fnName: string, args: array<expressionValue>) => {
|
||||||
let matchToDef = m => Matcher.Registry.matchToDef(r, m)
|
let matchToDef = m => Matcher.Registry.matchToDef(r, m)
|
||||||
let showNameMatchDefinitions = matches => {
|
let showNameMatchDefinitions = matches => {
|
||||||
|
|
|
@ -9,34 +9,37 @@ module Wrappers = {
|
||||||
}
|
}
|
||||||
|
|
||||||
module Prepare = {
|
module Prepare = {
|
||||||
let recordWithTwoArgsToValues = (inputs: array<value>): result<array<value>, string> =>
|
let recordWithTwoArgsToValues = (inputs: array<frValue>): result<array<frValue>, string> =>
|
||||||
switch inputs {
|
switch inputs {
|
||||||
| [Record([(_, n1), (_, n2)])] => Ok([n1, n2])
|
| [FRValueRecord([(_, n1), (_, n2)])] => Ok([n1, n2])
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleError)
|
||||||
}
|
}
|
||||||
|
|
||||||
let twoNumberInputs = (inputs: array<value>): result<(float, float), string> => {
|
let twoNumberInputs = (inputs: array<frValue>): result<(float, float), string> => {
|
||||||
switch inputs {
|
switch inputs {
|
||||||
| [Number(n1), Number(n2)] => Ok(n1, n2)
|
| [FRValueNumber(n1), FRValueNumber(n2)] => Ok(n1, n2)
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let twoDistOrNumber = (values: array<value>): result<(distOrNumber, distOrNumber), string> => {
|
let twoDistOrNumber = (values: array<frValue>): result<
|
||||||
|
(frValueDistOrNumber, frValueDistOrNumber),
|
||||||
|
string,
|
||||||
|
> => {
|
||||||
switch values {
|
switch values {
|
||||||
| [DistOrNumber(a1), DistOrNumber(a2)] => Ok(a1, a2)
|
| [FRValueDistOrNumber(a1), FRValueDistOrNumber(a2)] => Ok(a1, a2)
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let twoDistOrNumberFromRecord = (values: array<value>) =>
|
let twoDistOrNumberFromRecord = (values: array<frValue>) =>
|
||||||
values->recordWithTwoArgsToValues->E.R.bind(twoDistOrNumber)
|
values->recordWithTwoArgsToValues->E.R.bind(twoDistOrNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
module Process = {
|
module Process = {
|
||||||
let twoDistsOrNumbersToDist = (
|
let twoDistsOrNumbersToDist = (
|
||||||
~fn: ((float, float)) => result<DistributionTypes.genericDist, string>,
|
~fn: ((float, float)) => result<DistributionTypes.genericDist, string>,
|
||||||
~values: (distOrNumber, distOrNumber),
|
~values: (frValueDistOrNumber, frValueDistOrNumber),
|
||||||
) => {
|
) => {
|
||||||
let toSampleSet = r => GenericDist.toSampleSetDist(r, 1000)
|
let toSampleSet = r => GenericDist.toSampleSetDist(r, 1000)
|
||||||
let sampleSetToExpressionValue = (
|
let sampleSetToExpressionValue = (
|
||||||
|
@ -65,10 +68,10 @@ module Process = {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch values {
|
switch values {
|
||||||
| (Number(a1), Number(a2)) => fn((a1, a2))->E.R2.fmap(Wrappers.evDistribution)
|
| (FRValueNumber(a1), FRValueNumber(a2)) => fn((a1, a2))->E.R2.fmap(Wrappers.evDistribution)
|
||||||
| (Dist(a1), Number(a2)) => singleVarSample(a1, r => fn((r, a2)))
|
| (FRValueDist(a1), FRValueNumber(a2)) => singleVarSample(a1, r => fn((r, a2)))
|
||||||
| (Number(a1), Dist(a2)) => singleVarSample(a2, r => fn((a1, r)))
|
| (FRValueNumber(a1), FRValueDist(a2)) => singleVarSample(a2, r => fn((a1, r)))
|
||||||
| (Dist(a1), Dist(a2)) => {
|
| (FRValueDist(a1), FRValueDist(a2)) => {
|
||||||
let altFn = (a, b) => fn((a, b))->mapFnResult
|
let altFn = (a, b) => fn((a, b))->mapFnResult
|
||||||
let sampleSetResult =
|
let sampleSetResult =
|
||||||
E.R.merge(toSampleSet(a1), toSampleSet(a2))
|
E.R.merge(toSampleSet(a1), toSampleSet(a2))
|
||||||
|
@ -95,23 +98,23 @@ module TwoArgDist = {
|
||||||
r->E.R.bind(Process.twoDistsOrNumbersToDistUsingSymbolicDist(~fn, ~values=_))
|
r->E.R.bind(Process.twoDistsOrNumbersToDistUsingSymbolicDist(~fn, ~values=_))
|
||||||
|
|
||||||
let mkRegular = (name, fn) => {
|
let mkRegular = (name, fn) => {
|
||||||
Function.makeDefinition(~name, ~inputs=[I_DistOrNumber, I_DistOrNumber], ~run=inputs =>
|
FnDefinition.make(~name, ~inputs=[FRTypeDistOrNumber, FRTypeDistOrNumber], ~run=inputs =>
|
||||||
inputs->Prepare.twoDistOrNumber->process(~fn)
|
inputs->Prepare.twoDistOrNumber->process(~fn)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let mkDef90th = (name, fn) => {
|
let mkDef90th = (name, fn) => {
|
||||||
Function.makeDefinition(
|
FnDefinition.make(
|
||||||
~name,
|
~name,
|
||||||
~inputs=[I_Record([("p5", I_DistOrNumber), ("p95", I_DistOrNumber)])],
|
~inputs=[FRTypeRecord([("p5", FRTypeDistOrNumber), ("p95", FRTypeDistOrNumber)])],
|
||||||
~run=inputs => inputs->Prepare.twoDistOrNumberFromRecord->process(~fn),
|
~run=inputs => inputs->Prepare.twoDistOrNumberFromRecord->process(~fn),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let mkDefMeanStdev = (name, fn) => {
|
let mkDefMeanStdev = (name, fn) => {
|
||||||
Function.makeDefinition(
|
FnDefinition.make(
|
||||||
~name,
|
~name,
|
||||||
~inputs=[I_Record([("mean", I_DistOrNumber), ("stdev", I_DistOrNumber)])],
|
~inputs=[FRTypeRecord([("mean", FRTypeDistOrNumber), ("stdev", FRTypeDistOrNumber)])],
|
||||||
~run=inputs => inputs->Prepare.twoDistOrNumberFromRecord->process(~fn),
|
~run=inputs => inputs->Prepare.twoDistOrNumberFromRecord->process(~fn),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ let more = [
|
||||||
),
|
),
|
||||||
Function.make(
|
Function.make(
|
||||||
~name="To",
|
~name="To",
|
||||||
~definitions=[TwoArgDist.mkRegular("cauchy", twoArgs(SymbolicDist.From90thPercentile.make))],
|
~definitions=[TwoArgDist.mkRegular("to", twoArgs(SymbolicDist.From90thPercentile.make))],
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
Some functions from modules `L`, `O`, and `R` below were copied directly from
|
Some functions from modules `L`, `O`, and `R` below were copied directly from
|
||||||
running `rescript convert -all` on Rationale https://github.com/jonlaing/rationale
|
running `rescript convert -all` on Rationale https://github.com/jonlaing/rationale
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
let equals = (a,b) => a === b
|
||||||
|
|
||||||
module FloatFloatMap = {
|
module FloatFloatMap = {
|
||||||
module Id = Belt.Id.MakeComparable({
|
module Id = Belt.Id.MakeComparable({
|
||||||
type t = float
|
type t = float
|
||||||
|
|
Loading…
Reference in New Issue
Block a user