From fc407440530bb41f7cb714750818c16fb0644d9d Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Wed, 8 Jun 2022 08:00:06 -0700 Subject: [PATCH] Simple additions of first, last, cumulative sum, diff --- .../FunctionRegistry_Helpers.res | 11 +++- .../FunctionRegistry_Library.res | 61 +++++++++++++++---- .../squiggle-lang/src/rescript/Utility/E.res | 3 + 3 files changed, 63 insertions(+), 12 deletions(-) diff --git a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Helpers.res b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Helpers.res index b5ff2e75..9eb13837 100644 --- a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Helpers.res +++ b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Helpers.res @@ -236,7 +236,16 @@ module OneArgDist = { module ArrayNumberDist = { let make = (name, fn) => { FnDefinition.make(~name, ~inputs=[FRTypeArray(FRTypeNumber)], ~run=(inputs, _) => - Prepare.ToTypedArray.numbers(inputs)->E.R2.fmap(fn) + Prepare.ToTypedArray.numbers(inputs) + ->E.R.bind(r => E.A.length(r) === 0 ? Error("List is empty") : Ok(r)) + ->E.R.bind(fn) + ) + } + let make2 = (name, fn) => { + FnDefinition.make(~name, ~inputs=[FRTypeArray(FRTypeAny)], ~run=(inputs, _) => + Prepare.ToTypedArray.numbers(inputs) + ->E.R.bind(r => E.A.length(r) === 0 ? Error("List is empty") : Ok(r)) + ->E.R.bind(fn) ) } } diff --git a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Library.res b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Library.res index a2c07acd..12445f71 100644 --- a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Library.res +++ b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Library.res @@ -147,41 +147,63 @@ let registry = [ Function.make(~name="Round", ~definitions=[NumberToNumber.make("round", Js.Math.round)]), Function.make( ~name="Sum", - ~definitions=[ArrayNumberDist.make("sum", r => r->E.A.Floats.sum->Wrappers.evNumber)], + ~definitions=[ArrayNumberDist.make("sum", r => r->E.A.Floats.sum->Wrappers.evNumber->Ok)], ), Function.make( ~name="Product", - ~definitions=[ArrayNumberDist.make("product", r => r->E.A.Floats.product->Wrappers.evNumber)], + ~definitions=[ + ArrayNumberDist.make("product", r => r->E.A.Floats.product->Wrappers.evNumber->Ok), + ], ), Function.make( ~name="Min", - ~definitions=[ArrayNumberDist.make("min", r => r->E.A.Floats.min->Wrappers.evNumber)], + ~definitions=[ArrayNumberDist.make("min", r => r->E.A.Floats.min->Wrappers.evNumber->Ok)], ), Function.make( ~name="Max", - ~definitions=[ArrayNumberDist.make("max", r => r->E.A.Floats.max->Wrappers.evNumber)], + ~definitions=[ArrayNumberDist.make("max", r => r->E.A.Floats.max->Wrappers.evNumber->Ok)], ), Function.make( ~name="Mean", - ~definitions=[ArrayNumberDist.make("mean", r => r->E.A.Floats.mean->Wrappers.evNumber)], + ~definitions=[ArrayNumberDist.make("mean", r => r->E.A.Floats.mean->Wrappers.evNumber->Ok)], ), Function.make( ~name="Geometric Mean", - ~definitions=[ArrayNumberDist.make("geomean", r => r->E.A.Floats.geomean->Wrappers.evNumber)], + ~definitions=[ + ArrayNumberDist.make("geomean", r => r->E.A.Floats.geomean->Wrappers.evNumber->Ok), + ], ), Function.make( ~name="Standard Deviation", - ~definitions=[ArrayNumberDist.make("stdev", r => r->E.A.Floats.stdev->Wrappers.evNumber)], + ~definitions=[ArrayNumberDist.make("stdev", r => r->E.A.Floats.stdev->Wrappers.evNumber->Ok)], ), Function.make( ~name="Variance", - ~definitions=[ArrayNumberDist.make("variance", r => r->E.A.Floats.stdev->Wrappers.evNumber)], + ~definitions=[ + ArrayNumberDist.make("variance", r => r->E.A.Floats.stdev->Wrappers.evNumber->Ok), + ], + ), + Function.make( + ~name="First", + ~definitions=[ + ArrayNumberDist.make2("first", r => + r->E.A.first |> E.O.toResult(impossibleError) |> E.R.fmap(Wrappers.evNumber) + ), + ], + ), + Function.make( + ~name="Last", + ~definitions=[ + ArrayNumberDist.make2("last", r => + r->E.A.last |> E.O.toResult(impossibleError) |> E.R.fmap(Wrappers.evNumber) + ), + ], ), Function.make( ~name="Sort", ~definitions=[ ArrayNumberDist.make("sort", r => - r->E.A.Floats.sort->E.A2.fmap(Wrappers.evNumber)->Wrappers.evArray + r->E.A.Floats.sort->E.A2.fmap(Wrappers.evNumber)->Wrappers.evArray->Ok ), ], ), @@ -189,7 +211,23 @@ let registry = [ ~name="Reverse", ~definitions=[ ArrayNumberDist.make("reverse", r => - r->Belt_Array.reverse->E.A2.fmap(Wrappers.evNumber)->Wrappers.evArray + r->Belt_Array.reverse->E.A2.fmap(Wrappers.evNumber)->Wrappers.evArray->Ok + ), + ], + ), + Function.make( + ~name="Cumulative Sum", + ~definitions=[ + ArrayNumberDist.make("cumsum", r => + r->E.A.Floats.cumsum->E.A2.fmap(Wrappers.evNumber)->Wrappers.evArray->Ok + ), + ], + ), + Function.make( + ~name="Diff", + ~definitions=[ + ArrayNumberDist.make("diff", r => + r->E.A.Floats.diff->E.A2.fmap(Wrappers.evNumber)->Wrappers.evArray->Ok ), ], ), @@ -296,7 +334,8 @@ let registry = [ ->E.A.R.firstErrorOrOpen ->E.R2.fmap(Js.Dict.fromArray) ->E.R2.fmap(Wrappers.evRecord) - inputs->E.A.unsafe_get(0)->Prepare.ToValueArray.Array.arrayOfArrays |> E.R2.bind(convertInternalItems) + inputs->E.A.unsafe_get(0)->Prepare.ToValueArray.Array.arrayOfArrays + |> E.R2.bind(convertInternalItems) }), ], ), diff --git a/packages/squiggle-lang/src/rescript/Utility/E.res b/packages/squiggle-lang/src/rescript/Utility/E.res index d170a930..70ca4994 100644 --- a/packages/squiggle-lang/src/rescript/Utility/E.res +++ b/packages/squiggle-lang/src/rescript/Utility/E.res @@ -751,6 +751,9 @@ module A = { let diff = (t: t): array => Belt.Array.zipBy(t, Belt.Array.sliceToEnd(t, 1), (left, right) => right -. left) + let cumsum = (t: t): array => accumulate((a, b) => a +. b, t) + let cumProd = (t: t): array => accumulate((a, b) => a *. b, t) + exception RangeError(string) let range = (min: float, max: float, n: int): array => switch n {