Simple FunctionRegistry cleanup

This commit is contained in:
Ozzie Gooen 2022-05-21 11:41:12 -04:00
parent 7e2437bfc0
commit 40bf7443c9
4 changed files with 62 additions and 49 deletions

View File

@ -56,8 +56,8 @@ module FRType = {
| FRTypeOption(v) => `option(${toString(v)})` | FRTypeOption(v) => `option(${toString(v)})`
} }
let rec matchWithExpressionValue = (input: t, r: expressionValue): option<frValue> => let rec matchWithExpressionValue = (t: t, r: expressionValue): option<frValue> =>
switch (input, r) { switch (t, r) {
| (FRTypeNumber, EvNumber(f)) => Some(FRValueNumber(f)) | (FRTypeNumber, EvNumber(f)) => Some(FRValueNumber(f))
| (FRTypeDistOrNumber, EvNumber(f)) => Some(FRValueDistOrNumber(FRValueNumber(f))) | (FRTypeDistOrNumber, EvNumber(f)) => Some(FRValueDistOrNumber(FRValueNumber(f)))
| (FRTypeDistOrNumber, EvDistribution(Symbolic(#Float(f)))) => | (FRTypeDistOrNumber, EvDistribution(Symbolic(#Float(f)))) =>
@ -94,6 +94,11 @@ module FRType = {
} }
} }
/*
This module, Matcher, is fairly lengthy. However, only two functions from it
are meant to be used outside of it. These are findMatches and matchToDef in Matches.Registry.
The rest of it is just called from those two functions.
*/
module Matcher = { module Matcher = {
module MatchSimple = { module MatchSimple = {
type t = DifferentName | SameNameDifferentArguments | FullMatch type t = DifferentName | SameNameDifferentArguments | FullMatch
@ -185,21 +190,18 @@ module Matcher = {
} }
module Registry = { module Registry = {
let findExactMatches = (r: registry, fnName: string, args: array<expressionValue>) => { let _findExactMatches = (r: registry, fnName: string, args: array<expressionValue>) => {
let functionMatchPairs = r->E.A2.fmap(l => (l, Function.match(l, fnName, args))) let functionMatchPairs = r->E.A2.fmap(l => (l, Function.match(l, fnName, args)))
let getFullMatch = E.A.getBy(functionMatchPairs, ((_, match: Function.match)) => let fullMatch = functionMatchPairs->E.A.getBy(((_, match)) => Match.isFullMatch(match))
Match.isFullMatch(match) fullMatch->E.O.bind(((fn, match)) =>
)
let fullMatch: option<RegistryMatch.match> = getFullMatch->E.O.bind(((fn, match)) =>
switch match { switch match {
| FullMatch(index) => Some(RegistryMatch.makeMatch(fn.name, index)) | FullMatch(index) => Some(RegistryMatch.makeMatch(fn.name, index))
| _ => None | _ => None
} }
) )
fullMatch
} }
let findNameMatches = (r: registry, fnName: string, args: array<expressionValue>) => { let _findNameMatches = (r: registry, fnName: string, args: array<expressionValue>) => {
let functionMatchPairs = r->E.A2.fmap(l => (l, Function.match(l, fnName, args))) let functionMatchPairs = r->E.A2.fmap(l => (l, Function.match(l, fnName, args)))
let getNameMatches = let getNameMatches =
functionMatchPairs functionMatchPairs
@ -219,10 +221,10 @@ module Matcher = {
} }
let findMatches = (r: registry, fnName: string, args: array<expressionValue>) => { let findMatches = (r: registry, fnName: string, args: array<expressionValue>) => {
switch findExactMatches(r, fnName, args) { switch _findExactMatches(r, fnName, args) {
| Some(r) => Match.FullMatch(r) | Some(r) => Match.FullMatch(r)
| None => | None =>
switch findNameMatches(r, fnName, args) { switch _findNameMatches(r, fnName, args) {
| Some(r) => Match.SameNameDifferentArguments(r) | Some(r) => Match.SameNameDifferentArguments(r)
| None => Match.DifferentName | None => Match.DifferentName
} }
@ -241,7 +243,10 @@ module Matcher = {
module FnDefinition = { module FnDefinition = {
type t = fnDefinition type t = fnDefinition
let defToString = (t: t) => t.inputs->E.A2.fmap(FRType.toString)->E.A2.joinWith(", ") let toString = (t: t) => {
let inputs = t.inputs->E.A2.fmap(FRType.toString)->E.A2.joinWith(", ")
t.name ++ `(${inputs})`
}
let run = (t: t, args: array<expressionValue>) => { let run = (t: t, args: array<expressionValue>) => {
let argValues = FRType.matchWithExpressionValueArray(t.inputs, args) let argValues = FRType.matchWithExpressionValueArray(t.inputs, args)
@ -251,7 +256,7 @@ module FnDefinition = {
} }
} }
let make = (~name, ~inputs, ~run): fnDefinition => { let make = (~name, ~inputs, ~run): t => {
name: name, name: name,
inputs: inputs, inputs: inputs,
run: run, run: run,
@ -259,7 +264,9 @@ module FnDefinition = {
} }
module Function = { module Function = {
let make = (~name, ~definitions): function => { type t = function
let make = (~name, ~definitions): t => {
name: name, name: name,
definitions: definitions, definitions: definitions,
} }
@ -278,7 +285,8 @@ module Registry = {
matches matches
->E.A2.fmap(matchToDef) ->E.A2.fmap(matchToDef)
->E.A.O.concatSomes ->E.A.O.concatSomes
->E.A2.fmap(r => `[${fnName}(${FnDefinition.defToString(r)})]`) ->E.A2.fmap(FnDefinition.toString)
->E.A2.fmap(r => `[${r}]`)
->E.A2.joinWith("; ") ->E.A2.joinWith("; ")
`There are function matches for ${fnName}(), but with different arguments: ${defs}` `There are function matches for ${fnName}(), but with different arguments: ${defs}`
} }

View File

@ -9,44 +9,43 @@ module Wrappers = {
} }
module Prepare = { module Prepare = {
let recordWithTwoArgsToValues = (inputs: array<frValue>): result<array<frValue>, string> => type ts = array<frValue>
type err = string
module ToValueArray = {
module Record = {
let twoArgs = (inputs: ts): result<ts, err> =>
switch inputs { switch inputs {
| [FRValueRecord([(_, n1), (_, n2)])] => Ok([n1, n2]) | [FRValueRecord([(_, n1), (_, n2)])] => Ok([n1, n2])
| _ => Error(impossibleError) | _ => Error(impossibleError)
} }
let twoNumberInputs = (inputs: array<frValue>): result<(float, float), string> => {
switch inputs {
| [FRValueNumber(n1), FRValueNumber(n2)] => Ok(n1, n2)
| _ => Error(impossibleError)
} }
} }
let twoDistOrNumber = (values: array<frValue>): result< module ToValueTuple = {
(frValueDistOrNumber, frValueDistOrNumber), let twoDistOrNumber = (values: ts): result<(frValueDistOrNumber, frValueDistOrNumber), err> => {
string,
> => {
switch values { switch values {
| [FRValueDistOrNumber(a1), FRValueDistOrNumber(a2)] => Ok(a1, a2) | [FRValueDistOrNumber(a1), FRValueDistOrNumber(a2)] => Ok(a1, a2)
| _ => Error(impossibleError) | _ => Error(impossibleError)
} }
} }
let twoDistOrNumberFromRecord = (values: array<frValue>) => module Record = {
values->recordWithTwoArgsToValues->E.R.bind(twoDistOrNumber) let twoDistOrNumber = (values: ts): result<(frValueDistOrNumber, frValueDistOrNumber), err> =>
values->ToValueArray.Record.twoArgs->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: (frValueDistOrNumber, frValueDistOrNumber), ~values: (frValueDistOrNumber, frValueDistOrNumber),
) => { ): result<DistributionTypes.genericDist, string> => {
let toSampleSet = r => GenericDist.toSampleSetDist(r, 1000) let toSampleSet = r => GenericDist.toSampleSetDist(r, 1000)
let sampleSetToExpressionValue = ( let sampleSetToExpressionValue = (b: Belt.Result.t<SampleSetDist.t, DistributionTypes.error>) =>
b: Belt.Result.t<QuriSquiggleLang.SampleSetDist.t, QuriSquiggleLang.DistributionTypes.error>,
) =>
switch b { switch b {
| Ok(r) => Ok(ReducerInterface_ExpressionValue.EvDistribution(SampleSet(r))) | Ok(r) => Ok(DistributionTypes.SampleSet(r))
| Error(d) => Error(DistributionTypes.Error.toString(d)) | Error(d) => Error(DistributionTypes.Error.toString(d))
} }
@ -56,9 +55,11 @@ module Process = {
| Error(r) => Error(Operation.Other(r)) | Error(r) => Error(Operation.Other(r))
} }
let singleVarSample = (a, fn) => { let singleVarSample = (dist, fn) => {
let sampleSetResult = let sampleSetResult =
toSampleSet(a) |> E.R2.bind(dist => dist
->toSampleSet
->E.R.bind(dist =>
SampleSetDist.samplesMap( SampleSetDist.samplesMap(
~fn=f => fn(f)->mapFnResult, ~fn=f => fn(f)->mapFnResult,
dist, dist,
@ -68,7 +69,7 @@ module Process = {
} }
switch values { switch values {
| (FRValueNumber(a1), FRValueNumber(a2)) => fn((a1, a2))->E.R2.fmap(Wrappers.evDistribution) | (FRValueNumber(a1), FRValueNumber(a2)) => fn((a1, a2))
| (FRValueDist(a1), FRValueNumber(a2)) => singleVarSample(a1, r => fn((r, a2))) | (FRValueDist(a1), FRValueNumber(a2)) => singleVarSample(a1, r => fn((r, a2)))
| (FRValueNumber(a1), FRValueDist(a2)) => singleVarSample(a2, r => fn((a1, r))) | (FRValueNumber(a1), FRValueDist(a2)) => singleVarSample(a2, r => fn((a1, r)))
| (FRValueDist(a1), FRValueDist(a2)) => { | (FRValueDist(a1), FRValueDist(a2)) => {
@ -89,17 +90,20 @@ module Process = {
~fn: ((float, float)) => result<SymbolicDistTypes.symbolicDist, string>, ~fn: ((float, float)) => result<SymbolicDistTypes.symbolicDist, string>,
~values, ~values,
) => { ) => {
twoDistsOrNumbersToDist(~fn=r => r->fn->E.R2.fmap(Wrappers.symbolic), ~values) let newFn = r => fn(r)->E.R2.fmap(Wrappers.symbolic)
twoDistsOrNumbersToDist(~fn=newFn, ~values)
} }
} }
module TwoArgDist = { module TwoArgDist = {
let process = (~fn, r) => let process = (~fn, r) =>
r->E.R.bind(Process.twoDistsOrNumbersToDistUsingSymbolicDist(~fn, ~values=_)) r
->E.R.bind(Process.twoDistsOrNumbersToDistUsingSymbolicDist(~fn, ~values=_))
->E.R2.fmap(Wrappers.evDistribution)
let mkRegular = (name, fn) => { let mkRegular = (name, fn) => {
FnDefinition.make(~name, ~inputs=[FRTypeDistOrNumber, FRTypeDistOrNumber], ~run=inputs => FnDefinition.make(~name, ~inputs=[FRTypeDistOrNumber, FRTypeDistOrNumber], ~run=inputs =>
inputs->Prepare.twoDistOrNumber->process(~fn) inputs->Prepare.ToValueTuple.twoDistOrNumber->process(~fn)
) )
} }
@ -107,7 +111,7 @@ module TwoArgDist = {
FnDefinition.make( FnDefinition.make(
~name, ~name,
~inputs=[FRTypeRecord([("p5", FRTypeDistOrNumber), ("p95", FRTypeDistOrNumber)])], ~inputs=[FRTypeRecord([("p5", FRTypeDistOrNumber), ("p95", FRTypeDistOrNumber)])],
~run=inputs => inputs->Prepare.twoDistOrNumberFromRecord->process(~fn), ~run=inputs => inputs->Prepare.ToValueTuple.Record.twoDistOrNumber->process(~fn),
) )
} }
@ -115,7 +119,7 @@ module TwoArgDist = {
FnDefinition.make( FnDefinition.make(
~name, ~name,
~inputs=[FRTypeRecord([("mean", FRTypeDistOrNumber), ("stdev", FRTypeDistOrNumber)])], ~inputs=[FRTypeRecord([("mean", FRTypeDistOrNumber), ("stdev", FRTypeDistOrNumber)])],
~run=inputs => inputs->Prepare.twoDistOrNumberFromRecord->process(~fn), ~run=inputs => inputs->Prepare.ToValueTuple.Record.twoDistOrNumber->process(~fn),
) )
} }
} }

View File

@ -1,7 +1,7 @@
open FunctionRegistry_Core open FunctionRegistry_Core
open FunctionRegistry_Helpers open FunctionRegistry_Helpers
let twoArgs = (fn, (a1, a2)) => fn(a1, a2) let twoArgs = E.Tuple2.toFnCall
module NormalFn = { module NormalFn = {
let fnName = "normal" let fnName = "normal"
@ -56,4 +56,4 @@ let more = [
), ),
] ]
let allFunctions = [NormalFn.toFn, LognormalFn.toFn] let allFunctions = E.A.append([NormalFn.toFn, LognormalFn.toFn], more)

View File

@ -52,6 +52,7 @@ module Tuple2 = {
let (_, b) = v let (_, b) = v
b b
} }
let toFnCall = (fn, (a1, a2)) => fn(a1, a2)
} }
module O = { module O = {