From aa1fa5301e886b9657c8eb0d38cb87cef92a8305 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Fran=C3=A7ois?= Date: Wed, 4 Sep 2024 10:24:43 +0200 Subject: [PATCH] Add number round (#3533) --- .changeset/quick-roses-warn.md | 6 ++++++ packages/cli/src/internal/prompt/number.ts | 8 ++------ packages/effect/src/Number.ts | 23 ++++++++++++++++++++++ packages/effect/test/Number.test.ts | 9 +++++++++ 4 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 .changeset/quick-roses-warn.md diff --git a/.changeset/quick-roses-warn.md b/.changeset/quick-roses-warn.md new file mode 100644 index 0000000000..bc59fe60d3 --- /dev/null +++ b/.changeset/quick-roses-warn.md @@ -0,0 +1,6 @@ +--- +"effect": minor +"@effect/cli": patch +--- + +Add Number.round diff --git a/packages/cli/src/internal/prompt/number.ts b/packages/cli/src/internal/prompt/number.ts index fc7442eb7f..f2d69334bf 100644 --- a/packages/cli/src/internal/prompt/number.ts +++ b/packages/cli/src/internal/prompt/number.ts @@ -5,6 +5,7 @@ import * as Optimize from "@effect/printer/Optimize" import * as Schema from "@effect/schema/Schema" import * as Arr from "effect/Array" import * as Effect from "effect/Effect" +import * as EffectNumber from "effect/Number" import * as Option from "effect/Option" import type * as Prompt from "../../Prompt.js" import * as InternalPrompt from "../prompt.js" @@ -20,11 +21,6 @@ interface State { readonly error: Option.Option } -const round = (number: number, precision: number) => { - const factor = Math.pow(10, precision) - return Math.round(number * factor) / factor -} - const parseInt = Schema.NumberFromString.pipe( Schema.int(), Schema.decodeUnknown @@ -352,7 +348,7 @@ function handleProcessFloat(options: FloatOptions) { })), onSuccess: (n) => Effect.flatMap( - Effect.sync(() => round(n, options.precision)), + Effect.sync(() => EffectNumber.round(n, options.precision)), (rounded) => Effect.match(options.validate(rounded), { onFailure: (error) => diff --git a/packages/effect/src/Number.ts b/packages/effect/src/Number.ts index bd3181545b..ad5ea1a8e6 100644 --- a/packages/effect/src/Number.ts +++ b/packages/effect/src/Number.ts @@ -492,3 +492,26 @@ export const parse = (s: string): Option => { ? option.none : option.some(n) } + +/** + * Returns the number rounded with the given precision. + * + * @param self - The number to round + * @param precision - The precision + * + * @example + * import { round } from "effect/Number" + * + * assert.deepStrictEqual(round(1.1234, 2), 1.12) + * assert.deepStrictEqual(round(1.567, 2), 1.57) + * + * @category math + * @since 3.8.0 + */ +export const round: { + (precision: number): (self: number) => number + (self: number, precision: number): number +} = dual(2, (self: number, precision: number): number => { + const factor = Math.pow(10, precision) + return Math.round(self * factor) / factor +}) diff --git a/packages/effect/test/Number.test.ts b/packages/effect/test/Number.test.ts index 3e8f9c07e7..21b89b3347 100644 --- a/packages/effect/test/Number.test.ts +++ b/packages/effect/test/Number.test.ts @@ -135,4 +135,13 @@ describe("Number", () => { assert.deepStrictEqual(Number.parse("42"), Option.some(42)) assert.deepStrictEqual(Number.parse("a"), Option.none()) }) + + it("round", () => { + assert.deepStrictEqual(Number.round(1.1234, 2), 1.12) + assert.deepStrictEqual(Number.round(2)(1.1234), 1.12) + assert.deepStrictEqual(Number.round(0)(1.1234), 1) + assert.deepStrictEqual(Number.round(0)(1.1234), 1) + assert.deepStrictEqual(Number.round(1.567, 2), 1.57) + assert.deepStrictEqual(Number.round(2)(1.567), 1.57) + }) })