Skip to content

Commit

Permalink
Effect.mapAccum & Array.mapAccum preserve non-emptiness (#3675)
Browse files Browse the repository at this point in the history
Co-authored-by: maksim.khramtsov <maksim.khramtsov@btsdigital.kz>
  • Loading branch information
2 people authored and tim-smart committed Oct 6, 2024
1 parent 9237ac6 commit 0779681
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 18 deletions.
5 changes: 5 additions & 0 deletions .changeset/healthy-dogs-judge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": minor
---

Effect.mapAccum & Array.mapAccum preserve non-emptiness
21 changes: 21 additions & 0 deletions packages/effect/dtslint/Array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1504,3 +1504,24 @@ pipe(
_n // $ExpectType 1 | 2
) => "a" as const)
)

// -------------------------------------------------------------------------------------
// mapAccum
// -------------------------------------------------------------------------------------

// $ExpectType [state: number, mappedArray: string[]]
Array.mapAccum(strings, 0, (s, a, i) => [s + i, a])

// $ExpectType [state: number, mappedArray: [string, ...string[]]]
Array.mapAccum(nonEmptyReadonlyStrings, 0, (s, a, i) => [s + i, a])

// $ExpectType [state: number, mappedArray: string[]]
pipe(
strings,
Array.mapAccum(0, (s, a, i) => [s + i, a])
)
// $ExpectType [state: number, mappedArray: [string, ...string[]]]
pipe(
nonEmptyReadonlyStrings,
Array.mapAccum(0, (s, a, i) => [s + i, a])
)
25 changes: 25 additions & 0 deletions packages/effect/dtslint/Effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1263,3 +1263,28 @@ pipe(
) => "b" as const
)
)

// -------------------------------------------------------------------------------------
// mapAccum
// -------------------------------------------------------------------------------------

declare const nonEmptyReadonlyStrings: NonEmptyReadonlyArray<string>
declare const strings: Array<string>

// $ExpectType Effect<[number, string[]], never, never>
Effect.mapAccum(strings, 0, (s, a, i) => Effect.succeed([s + i, a]))

// $ExpectType Effect<[number, [string, ...string[]]], never, never>
Effect.mapAccum(nonEmptyReadonlyStrings, 0, (s, a, i) => Effect.succeed([s + i, a]))

// $ExpectType Effect<[number, string[]], never, never>
pipe(
strings,
Effect.mapAccum(0, (s, a, i) => Effect.succeed([s + i, a]))
)

// $ExpectType Effect<[number, [string, ...string[]]], never, never>
pipe(
nonEmptyReadonlyStrings,
Effect.mapAccum(0, (s, a, i) => Effect.succeed([s + i, a]))
)
12 changes: 8 additions & 4 deletions packages/effect/src/Array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2859,11 +2859,15 @@ export const join: {
* @category folding
*/
export const mapAccum: {
<S, A, B>(
<S, A, B, I extends Iterable<A> = Iterable<A>>(
s: S,
f: (s: S, a: A, i: number) => readonly [S, B]
): (self: Iterable<A>) => [state: S, mappedArray: Array<B>]
<S, A, B>(self: Iterable<A>, s: S, f: (s: S, a: A, i: number) => readonly [S, B]): [state: S, mappedArray: Array<B>]
f: (s: S, a: ReadonlyArray.Infer<I>, i: number) => readonly [S, B]
): (self: I) => [state: S, mappedArray: ReadonlyArray.With<I, B>]
<S, A, B, I extends Iterable<A> = Iterable<A>>(
self: I,
s: S,
f: (s: S, a: ReadonlyArray.Infer<I>, i: number) => readonly [S, B]
): [state: S, mappedArray: ReadonlyArray.With<I, B>]
} = dual(
3,
<S, A, B>(self: Iterable<A>, s: S, f: (s: S, a: A, i: number) => [S, B]): [state: S, mappedArray: Array<B>] => {
Expand Down
14 changes: 7 additions & 7 deletions packages/effect/src/Effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2365,15 +2365,15 @@ export const map: {
* @category mapping
*/
export const mapAccum: {
<S, A, B, E, R>(
<S, A, B, E, R, I extends Iterable<A> = Iterable<A>>(
zero: S,
f: (s: S, a: A, i: number) => Effect<readonly [S, B], E, R>
): (elements: Iterable<A>) => Effect<[S, Array<B>], E, R>
<A, S, B, E, R>(
elements: Iterable<A>,
f: (s: S, a: RA.ReadonlyArray.Infer<I>, i: number) => Effect<readonly [S, B], E, R>
): (elements: I) => Effect<[S, RA.ReadonlyArray.With<I, B>], E, R>
<A, S, B, E, R, I extends Iterable<A> = Iterable<A>>(
elements: I,
zero: S,
f: (s: S, a: A, i: number) => Effect<readonly [S, B], E, R>
): Effect<[S, Array<B>], E, R>
f: (s: S, a: RA.ReadonlyArray.Infer<I>, i: number) => Effect<readonly [S, B], E, R>
): Effect<[S, RA.ReadonlyArray.With<I, B>], E, R>
} = effect.mapAccum

/**
Expand Down
14 changes: 7 additions & 7 deletions packages/effect/src/internal/core-effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1055,17 +1055,17 @@ const loopDiscard = <S, X, E, R>(

/* @internal */
export const mapAccum: {
<S, A, B, E, R>(
<S, A, B, E, R, I extends Iterable<A> = Iterable<A>>(
zero: S,
f: (s: S, a: A, i: number) => Effect.Effect<readonly [S, B], E, R>
): (elements: Iterable<A>) => Effect.Effect<[S, Array<B>], E, R>
<A, S, B, E, R>(
elements: Iterable<A>,
): (elements: I) => Effect.Effect<[S, Arr.ReadonlyArray.With<I, B>], E, R>
<A, S, B, E, R, I extends Iterable<A> = Iterable<A>>(
elements: I,
zero: S,
f: (s: S, a: A, i: number) => Effect.Effect<readonly [S, B], E, R>
): Effect.Effect<[S, Array<B>], E, R>
} = dual(3, <A, S, B, E, R>(
elements: Iterable<A>,
): Effect.Effect<[S, Arr.ReadonlyArray.With<I, B>], E, R>
} = dual(3, <A, S, B, E, R, I extends Iterable<A> = Iterable<A>>(
elements: I,
zero: S,
f: (s: S, a: A, i: number) => Effect.Effect<readonly [S, B], E, R>
): Effect.Effect<[S, Array<B>], E, R> =>
Expand Down

0 comments on commit 0779681

Please sign in to comment.