diff --git a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Core.res b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Core.res index 5e9e877e..fcb27cbe 100644 --- a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Core.res +++ b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Core.res @@ -56,8 +56,8 @@ module FRType = { | FRTypeOption(v) => `option(${toString(v)})` } - let rec matchWithExpressionValue = (input: t, r: expressionValue): option => - switch (input, r) { + let rec matchWithExpressionValue = (t: t, r: expressionValue): option => + switch (t, r) { | (FRTypeNumber, EvNumber(f)) => Some(FRValueNumber(f)) | (FRTypeDistOrNumber, EvNumber(f)) => Some(FRValueDistOrNumber(FRValueNumber(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 MatchSimple = { type t = DifferentName | SameNameDifferentArguments | FullMatch @@ -185,21 +190,18 @@ module Matcher = { } module Registry = { - let findExactMatches = (r: registry, fnName: string, args: array) => { + let _findExactMatches = (r: registry, fnName: string, args: array) => { let functionMatchPairs = r->E.A2.fmap(l => (l, Function.match(l, fnName, args))) - let getFullMatch = E.A.getBy(functionMatchPairs, ((_, match: Function.match)) => - Match.isFullMatch(match) - ) - let fullMatch: option = getFullMatch->E.O.bind(((fn, match)) => + let fullMatch = functionMatchPairs->E.A.getBy(((_, match)) => Match.isFullMatch(match)) + fullMatch->E.O.bind(((fn, match)) => switch match { | FullMatch(index) => Some(RegistryMatch.makeMatch(fn.name, index)) | _ => None } ) - fullMatch } - let findNameMatches = (r: registry, fnName: string, args: array) => { + let _findNameMatches = (r: registry, fnName: string, args: array) => { let functionMatchPairs = r->E.A2.fmap(l => (l, Function.match(l, fnName, args))) let getNameMatches = functionMatchPairs @@ -219,10 +221,10 @@ module Matcher = { } let findMatches = (r: registry, fnName: string, args: array) => { - switch findExactMatches(r, fnName, args) { + switch _findExactMatches(r, fnName, args) { | Some(r) => Match.FullMatch(r) | None => - switch findNameMatches(r, fnName, args) { + switch _findNameMatches(r, fnName, args) { | Some(r) => Match.SameNameDifferentArguments(r) | None => Match.DifferentName } @@ -241,7 +243,10 @@ module Matcher = { module 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) => { 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, inputs: inputs, run: run, @@ -259,7 +264,9 @@ module FnDefinition = { } module Function = { - let make = (~name, ~definitions): function => { + type t = function + + let make = (~name, ~definitions): t => { name: name, definitions: definitions, } @@ -278,7 +285,8 @@ module Registry = { matches ->E.A2.fmap(matchToDef) ->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("; ") `There are function matches for ${fnName}(), but with different arguments: ${defs}` } diff --git a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Helpers.res b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Helpers.res index 8ef27a6c..6daeace1 100644 --- a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Helpers.res +++ b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Helpers.res @@ -9,44 +9,43 @@ module Wrappers = { } module Prepare = { - let recordWithTwoArgsToValues = (inputs: array): result, string> => - switch inputs { - | [FRValueRecord([(_, n1), (_, n2)])] => Ok([n1, n2]) - | _ => Error(impossibleError) - } + type ts = array + type err = string - let twoNumberInputs = (inputs: array): result<(float, float), string> => { - switch inputs { - | [FRValueNumber(n1), FRValueNumber(n2)] => Ok(n1, n2) - | _ => Error(impossibleError) + module ToValueArray = { + module Record = { + let twoArgs = (inputs: ts): result => + switch inputs { + | [FRValueRecord([(_, n1), (_, n2)])] => Ok([n1, n2]) + | _ => Error(impossibleError) + } } } - let twoDistOrNumber = (values: array): result< - (frValueDistOrNumber, frValueDistOrNumber), - string, - > => { - switch values { - | [FRValueDistOrNumber(a1), FRValueDistOrNumber(a2)] => Ok(a1, a2) - | _ => Error(impossibleError) + module ToValueTuple = { + let twoDistOrNumber = (values: ts): result<(frValueDistOrNumber, frValueDistOrNumber), err> => { + switch values { + | [FRValueDistOrNumber(a1), FRValueDistOrNumber(a2)] => Ok(a1, a2) + | _ => Error(impossibleError) + } + } + + module Record = { + let twoDistOrNumber = (values: ts): result<(frValueDistOrNumber, frValueDistOrNumber), err> => + values->ToValueArray.Record.twoArgs->E.R.bind(twoDistOrNumber) } } - - let twoDistOrNumberFromRecord = (values: array) => - values->recordWithTwoArgsToValues->E.R.bind(twoDistOrNumber) } module Process = { let twoDistsOrNumbersToDist = ( ~fn: ((float, float)) => result, ~values: (frValueDistOrNumber, frValueDistOrNumber), - ) => { + ): result => { let toSampleSet = r => GenericDist.toSampleSetDist(r, 1000) - let sampleSetToExpressionValue = ( - b: Belt.Result.t, - ) => + let sampleSetToExpressionValue = (b: Belt.Result.t) => switch b { - | Ok(r) => Ok(ReducerInterface_ExpressionValue.EvDistribution(SampleSet(r))) + | Ok(r) => Ok(DistributionTypes.SampleSet(r)) | Error(d) => Error(DistributionTypes.Error.toString(d)) } @@ -56,9 +55,11 @@ module Process = { | Error(r) => Error(Operation.Other(r)) } - let singleVarSample = (a, fn) => { + let singleVarSample = (dist, fn) => { let sampleSetResult = - toSampleSet(a) |> E.R2.bind(dist => + dist + ->toSampleSet + ->E.R.bind(dist => SampleSetDist.samplesMap( ~fn=f => fn(f)->mapFnResult, dist, @@ -68,7 +69,7 @@ module Process = { } 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))) | (FRValueNumber(a1), FRValueDist(a2)) => singleVarSample(a2, r => fn((a1, r))) | (FRValueDist(a1), FRValueDist(a2)) => { @@ -89,17 +90,20 @@ module Process = { ~fn: ((float, float)) => result, ~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 = { 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) => { 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( ~name, ~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( ~name, ~inputs=[FRTypeRecord([("mean", FRTypeDistOrNumber), ("stdev", FRTypeDistOrNumber)])], - ~run=inputs => inputs->Prepare.twoDistOrNumberFromRecord->process(~fn), + ~run=inputs => inputs->Prepare.ToValueTuple.Record.twoDistOrNumber->process(~fn), ) } } diff --git a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Library.res b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Library.res index d998191f..705da963 100644 --- a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Library.res +++ b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Library.res @@ -1,7 +1,7 @@ open FunctionRegistry_Core open FunctionRegistry_Helpers -let twoArgs = (fn, (a1, a2)) => fn(a1, a2) +let twoArgs = E.Tuple2.toFnCall module NormalFn = { 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) diff --git a/packages/squiggle-lang/src/rescript/Utility/E.res b/packages/squiggle-lang/src/rescript/Utility/E.res index 1916b8b1..3357f4f4 100644 --- a/packages/squiggle-lang/src/rescript/Utility/E.res +++ b/packages/squiggle-lang/src/rescript/Utility/E.res @@ -52,6 +52,7 @@ module Tuple2 = { let (_, b) = v b } + let toFnCall = (fn, (a1, a2)) => fn(a1, a2) } module O = {