Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/spicy-tigers-dig.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": patch
---

Improve `Predicate.all` and `Predicate.some` to support heterogeneous collections
7 changes: 3 additions & 4 deletions packages/effect/src/Array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { dual, identity } from "./Function.js"
import type { TypeLambda } from "./HKT.js"
import * as internalArray from "./internal/array.js"
import * as internalDoNotation from "./internal/doNotation.js"
import * as moduleIterable from "./Iterable.js"
import * as Iterable_ from "./Iterable.js"
import * as Option from "./Option.js"
import * as Order from "./Order.js"
import * as Predicate from "./Predicate.js"
Expand Down Expand Up @@ -1057,7 +1057,7 @@ export const findFirst: {
<A, B>(self: Iterable<A>, f: (a: A, i: number) => Option.Option<B>): Option.Option<B>
<A, B extends A>(self: Iterable<A>, refinement: (a: A, i: number) => a is B): Option.Option<B>
<A>(self: Iterable<A>, predicate: (a: A, i: number) => boolean): Option.Option<A>
} = moduleIterable.findFirst
} = Iterable_.findFirst

/**
* Finds the last element in an iterable collection that satisfies the given predicate or refinement.
Expand Down Expand Up @@ -2441,8 +2441,7 @@ export declare namespace ReadonlyArray {
* @since 2.0.0
*/
export type Infer<S extends Iterable<any>> = S extends ReadonlyArray<infer A> ? A
: S extends Iterable<infer A> ? A
: never
: Iterable_.Iterable.Infer<S>

/**
* @since 2.0.0
Expand Down
23 changes: 23 additions & 0 deletions packages/effect/src/Iterable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,29 @@ import type * as Record from "./Record.js"
import * as Tuple from "./Tuple.js"
import type { NoInfer } from "./Types.js"

/**
* @since 3.8.14
*/
export declare namespace Iterable {
/**
* @since 3.8.14
*/
export type Infer<S extends Iterable<any>> = S extends Iterable<infer A, infer _R, infer _N> ? A
: never

/**
* @since 3.8.14
*/
export type Return<S extends Iterable<any>> = S extends Iterable<infer _A, infer R, infer _N> ? R
: never

/**
* @since 3.8.14
*/
export type Next<S extends Iterable<any>> = S extends Iterable<infer _A, infer _R, infer N> ? N
: never
}

/**
* Return a `Iterable` with element `i` initialized with `f(i)`.
*
Expand Down
31 changes: 25 additions & 6 deletions packages/effect/src/Predicate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
import { dual, isFunction as isFunction_ } from "./Function.js"
import type { TypeLambda } from "./HKT.js"
import type { Iterable as Iterable_ } from "./Iterable.js"
import type { TupleOf, TupleOfAtLeast } from "./Types.js"

/**
Expand Down Expand Up @@ -948,12 +949,19 @@ export const product =
*
* @category combining
* @since 2.0.0
* @see tuple for a more powerful, variadic version.
*/
export const all = <A>(
collection: Iterable<Predicate<A>>
): Predicate<ReadonlyArray<A>> => {
return (as) => {
export const all: {
<A extends Iterable<Refinement.Any>>(
collection: A
): Refinement<
Array<Refinement.In<Iterable_.Infer<A>>>,
Array<Refinement.Out<Iterable_.Infer<A>>>
>
<A extends Iterable<Predicate.Any>>(collection: A): Predicate<Array<Predicate.In<Iterable_.Infer<A>>>>
} = <A extends Iterable<Refinement.Any>>(
collection: A
) => {
return (as: Array<Refinement.In<Iterable_.Infer<A>>>): as is Array<Refinement.Out<Iterable_.Infer<A>>> => {
let collectionIndex = 0
for (const p of collection) {
if (collectionIndex >= as.length) {
Expand Down Expand Up @@ -1395,7 +1403,18 @@ export const every = <A>(collection: Iterable<Predicate<A>>): Predicate<A> => (a
* @since 2.0.0
* @see every
*/
export const some = <A>(collection: Iterable<Predicate<A>>): Predicate<A> => (a) => {
export const some: {
<A extends Iterable<Refinement.Any>>(
collection: A
): Refinement<
Refinement.In<Iterable_.Infer<A>>,
Refinement.Out<Iterable_.Infer<A>>
>
<A extends Iterable<Predicate.Any>>(collection: A): Predicate<Predicate.In<Iterable_.Infer<A>>>
} = <A extends Iterable<Refinement.Any>>(
collection: A
) =>
(a: Refinement.In<Iterable_.Infer<A>>): a is Refinement.Out<Iterable_.Infer<A>> => {
for (const p of collection) {
if (p(a)) {
return true
Expand Down