open FunctionRegistry_Core open FunctionRegistry_Helpers let nameSpace = "Plot" module FnApp = { type fnApp<'a> = { result: Reducer_T.value => result<'a, SqError.Message.t>, typeRequired: frType, } let fmap = (f: 'a => 'b, m: fnApp<'a>): fnApp<'b> => { { result: (a: Reducer_T.value) => E.R.fmap(f, m.result(a)), typeRequired: m.typeRequired, } } module Record = { type t<'a> = { result: Reducer_T.map => result<'a, SqError.Message.t>, typesRequired: array<(string, frType)>, } let getField = (key: string, parser: fnApp<'a>): t<'a> => { let func = (a: Reducer_T.map) => switch Belt.Map.String.get(a, key) { | Some(x) => parser.result(x) | None => Error(impossibleError) } {result: func, typesRequired: [(key, parser.typeRequired)]} } let merge = (m1: t<'a>, m2: t<'b>): t<('a, 'b)> => { { result: (a: Reducer_T.map) => E.R.merge(m1.result(a), m2.result(a)), typesRequired: Belt.Array.concat(m1.typesRequired, m2.typesRequired), } } let fmap = (f: 'a => 'b, m: t<'a>): t<'b> => { { result: (a: Reducer_T.map) => E.R.fmap(f, m.result(a)), typesRequired: m.typesRequired, } } let app = (m1: t<'a => 'b>, m2: t<'a>): t<'b> => { { result: (a: Reducer_T.map) => E.R.merge(m1.result(a), m2.result(a))->E.R2.fmap(((f, x)) => f(x)), typesRequired: Belt.Array.concat(m1.typesRequired, m2.typesRequired), } } } let getString: fnApp = { let func = (a: Reducer_T.value) => switch a { | IEvString(s) => Ok(s) | _ => Error(impossibleError) } {result: func, typeRequired: FRTypeString} } let getArray = (child: fnApp<'a>): fnApp> => { let func = (a: Reducer_T.value) => switch a { | IEvArray(x) => x->E.A2.fmap(child.result)->E.A.R.firstErrorOrOpen | _ => Error(impossibleError) } {result: func, typeRequired: FRTypeArray(child.typeRequired)} } let getRecord = (recMonad: Record.t<'a>): fnApp<'a> => { let func = (a: Reducer_T.value) => switch a { | IEvRecord(s) => recMonad.result(s) | _ => Error(impossibleError) } {result: func, typeRequired: FRTypeRecord(recMonad.typesRequired)} } let getDistOrNumber: fnApp = { let func = (a: Reducer_T.value) => switch a { | IEvDistribution(s) => Ok(s) | IEvNumber(s) => Ok(GenericDist.fromFloat(s)) | _ => Error(impossibleError) } {result: func, typeRequired: FRTypeDistOrNumber} } let oneArgDef = ( name: string, arg1: fnApp<'a>, def: 'a => result, ): FnDefinition.t => FnDefinition.make( ~name, ~inputs=[arg1.typeRequired], ~run=(inputs, _, _) => { E.R.bind(arg1.result(inputs[0]), def) }, (), ) } module Internals = { let makeLabeledDistribution = ( name: string, distribution: GenericDist.t, ): Reducer_T.labeledDistribution => {name: name, distribution: distribution} let getLabeledDistribution: FnApp.fnApp = { makeLabeledDistribution ->FnApp.Record.fmap(FnApp.Record.getField("name", FnApp.getString)) ->FnApp.Record.app(FnApp.Record.getField("value", FnApp.getDistOrNumber)) ->FnApp.getRecord } let makePlot = (show: array): Reducer_T.plotValue => { distributions: show, } let parsePlotValue: FnApp.fnApp = { makePlot ->FnApp.Record.fmap(FnApp.Record.getField("show", FnApp.getArray(getLabeledDistribution))) ->FnApp.getRecord } } let library = [ Function.make( ~name="dist", ~nameSpace, ~requiresNamespace=true, ~output=EvtPlot, ~examples=[ `Plot.dist({show: [{name: "Control", value: 1 to 2}, {name: "Treatment", value: 1.5 to 2.5}]}) `, ], ~definitions=[ FnApp.oneArgDef("dist", Internals.parsePlotValue, (a: Reducer_T.plotValue) => Ok(IEvPlot(a))), ], (), ), ]