Skip to content

Commit

Permalink
feat: foreach preserve non emptyness. (#2608)
Browse files Browse the repository at this point in the history
Co-authored-by: Tim <hello@timsmart.co>
  • Loading branch information
patroza and tim-smart committed Apr 25, 2024
1 parent 6222404 commit 868ed2a
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 13 deletions.
5 changes: 5 additions & 0 deletions .changeset/fair-adults-chew.md
@@ -0,0 +1,5 @@
---
"effect": patch
---

feat: foreach preserve non emptyness.
91 changes: 88 additions & 3 deletions packages/effect/dtslint/Effect.ts
@@ -1,3 +1,4 @@
import type { NonEmptyReadonlyArray } from "effect/Array"
import type { Cause } from "effect/Cause"
import * as Effect from "effect/Effect"
import { pipe } from "effect/Function"
Expand All @@ -15,19 +16,19 @@ declare const numberArray: Array<number>
declare const numberEffectIterable: Array<Effect.Effect<number>>

// -------------------------------------------------------------------------------------
// forEach
// forEach - array
// -------------------------------------------------------------------------------------

// $ExpectType Effect<string[], "err-1", "dep-1">
Effect.forEach(["a", "b"], (
Effect.forEach(["a", "b"] as Array<string>, (
// $ExpectType string
_a,
// $ExpectType number
_i
) => string)

// $ExpectType Effect<void, "err-1", "dep-1">
Effect.forEach(["a", "b"], (
Effect.forEach(["a", "b"] as Array<string>, (
// $ExpectType string
_a,
// $ExpectType number
Expand Down Expand Up @@ -56,6 +57,90 @@ pipe(
) => string, { discard: true })
)

// -------------------------------------------------------------------------------------
// forEach - nonempty
// -------------------------------------------------------------------------------------

// $ExpectType Effect<[string, ...string[]], "err-1", "dep-1">
Effect.forEach(["a", "b"], (
// $ExpectType string
_a,
// $ExpectType number
_i
) => string)

// $ExpectType Effect<void, "err-1", "dep-1">
Effect.forEach(["a", "b"], (
// $ExpectType string
_a,
// $ExpectType number
_i
) => string, { discard: true })

// $ExpectType Effect<[string, ...string[]], "err-1", "dep-1">
pipe(
["a", "b"] as NonEmptyReadonlyArray<string>,
Effect.forEach((
// $ExpectType string
_a,
// $ExpectType number
_i
) => string)
)

// $ExpectType Effect<void, "err-1", "dep-1">
pipe(
["a", "b"] as NonEmptyReadonlyArray<string>,
Effect.forEach((
// $ExpectType string
_a,
// $ExpectType number
_i
) => string, { discard: true })
)

// -------------------------------------------------------------------------------------
// forEach - tuple as non empty array
// -------------------------------------------------------------------------------------

// $ExpectType Effect<[string, ...string[]], "err-1", "dep-1">
Effect.forEach(["a", "b"] as const, (
// $ExpectType "a" | "b"
_a,
// $ExpectType number
_i
) => string)

// $ExpectType Effect<void, "err-1", "dep-1">
Effect.forEach(["a", "b"] as const, (
// $ExpectType "a" | "b"
_a,
// $ExpectType number
_i
) => string, { discard: true })

// $ExpectType Effect<[string, ...string[]], "err-1", "dep-1">
pipe(
["a", "b"] as const,
Effect.forEach((
// $ExpectType "a" | "b"
_a,
// $ExpectType number
_i
) => string)
)

// $ExpectType Effect<void, "err-1", "dep-1">
pipe(
["a", "b"] as const,
Effect.forEach((
// $ExpectType "a" | "b"
_a,
// $ExpectType number
_i
) => string, { discard: true })
)

// -------------------------------------------------------------------------------------
// all - tuple
// -------------------------------------------------------------------------------------
Expand Down
21 changes: 16 additions & 5 deletions packages/effect/src/Effect.ts
@@ -1,6 +1,7 @@
/**
* @since 2.0.0
*/
import type * as RA from "./Array.js"
import type * as Cause from "./Cause.js"
import type * as Chunk from "./Chunk.js"
import type * as Clock from "./Clock.js"
Expand Down Expand Up @@ -648,20 +649,21 @@ export const findFirst: {
export const firstSuccessOf: <Eff extends Effect<any, any, any>>(
effects: Iterable<Eff>
) => Effect<Effect.Success<Eff>, Effect.Error<Eff>, Effect.Context<Eff>> = effect.firstSuccessOf

/**
* @since 2.0.0
* @category collecting & elements
*/
export const forEach: {
<A, B, E, R>(
f: (a: A, i: number) => Effect<B, E, R>,
<B, E, R, S extends Iterable<any>>(
f: (a: RA.ReadonlyArray.Infer<S>, i: number) => Effect<B, E, R>,
options?: {
readonly concurrency?: Concurrency | undefined
readonly batching?: boolean | "inherit" | undefined
readonly discard?: false | undefined
} | undefined
): (self: Iterable<A>) => Effect<Array<B>, E, R>
): (
self: S
) => Effect<RA.ReadonlyArray.With<S, B>, E, R>
<A, B, E, R>(
f: (a: A, i: number) => Effect<B, E, R>,
options: {
Expand All @@ -670,6 +672,15 @@ export const forEach: {
readonly discard: true
}
): (self: Iterable<A>) => Effect<void, E, R>
<A, B, E, R>(
self: RA.NonEmptyReadonlyArray<A>,
f: (a: A, i: number) => Effect<B, E, R>,
options?: {
readonly concurrency?: Concurrency | undefined
readonly batching?: boolean | "inherit" | undefined
readonly discard?: false | undefined
} | undefined
): Effect<RA.NonEmptyArray<B>, E, R>
<A, B, E, R>(
self: Iterable<A>,
f: (a: A, i: number) => Effect<B, E, R>,
Expand All @@ -688,7 +699,7 @@ export const forEach: {
readonly discard: true
}
): Effect<void, E, R>
} = fiberRuntime.forEach
} = fiberRuntime.forEach as any

/**
* Returns a successful effect with the head of the collection if the collection
Expand Down
21 changes: 16 additions & 5 deletions packages/effect/src/internal/fiberRuntime.ts
Expand Up @@ -1883,14 +1883,16 @@ export const replicateEffect: {

/* @internal */
export const forEach: {
<A, B, E, R>(
f: (a: A, i: number) => Effect.Effect<B, E, R>,
<B, E, R, S extends Iterable<any>>(
f: (a: RA.ReadonlyArray.Infer<S>, i: number) => Effect.Effect<B, E, R>,
options?: {
readonly concurrency?: Concurrency | undefined
readonly batching?: boolean | "inherit" | undefined
readonly discard?: false | undefined
}
): (self: Iterable<A>) => Effect.Effect<Array<B>, E, R>
} | undefined
): (
self: S
) => Effect.Effect<RA.ReadonlyArray.With<S, B>, E, R>
<A, B, E, R>(
f: (a: A, i: number) => Effect.Effect<B, E, R>,
options: {
Expand All @@ -1899,14 +1901,23 @@ export const forEach: {
readonly discard: true
}
): (self: Iterable<A>) => Effect.Effect<void, E, R>
<A, B, E, R>(
self: RA.NonEmptyReadonlyArray<A>,
f: (a: A, i: number) => Effect.Effect<B, E, R>,
options?: {
readonly concurrency?: Concurrency | undefined
readonly batching?: boolean | "inherit" | undefined
readonly discard?: false | undefined
} | undefined
): Effect.Effect<RA.NonEmptyArray<B>, E, R>
<A, B, E, R>(
self: Iterable<A>,
f: (a: A, i: number) => Effect.Effect<B, E, R>,
options?: {
readonly concurrency?: Concurrency | undefined
readonly batching?: boolean | "inherit" | undefined
readonly discard?: false | undefined
}
} | undefined
): Effect.Effect<Array<B>, E, R>
<A, B, E, R>(
self: Iterable<A>,
Expand Down

0 comments on commit 868ed2a

Please sign in to comment.