Skip to content

Commit

Permalink
allow tacit usage with do notation apis (.bind / .let) (#3768)
Browse files Browse the repository at this point in the history
  • Loading branch information
tim-smart authored Oct 11, 2024
1 parent e99a9c3 commit 61a99b2
Show file tree
Hide file tree
Showing 13 changed files with 63 additions and 59 deletions.
6 changes: 6 additions & 0 deletions .changeset/polite-carrots-push.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@effect/typeclass": patch
"effect": patch
---

allow tacit usage with do notation apis (.bind / .let)
8 changes: 4 additions & 4 deletions packages/effect/src/Array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3057,14 +3057,14 @@ export const Do: ReadonlyArray<{}> = of({})
export const bind: {
<A extends object, N extends string, B>(
tag: Exclude<N, keyof A>,
f: (a: A) => ReadonlyArray<B>
f: (a: NoInfer<A>) => ReadonlyArray<B>
): (
self: ReadonlyArray<A>
) => Array<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }>
<A extends object, N extends string, B>(
self: ReadonlyArray<A>,
tag: Exclude<N, keyof A>,
f: (a: A) => ReadonlyArray<B>
f: (a: NoInfer<A>) => ReadonlyArray<B>
): Array<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }>
} = doNotation.bind<ReadonlyArrayTypeLambda>(map, flatMap) as any

Expand Down Expand Up @@ -3119,12 +3119,12 @@ export const bindTo: {
const let_: {
<N extends string, B, A extends object>(
tag: Exclude<N, keyof A>,
f: (a: A) => B
f: (a: NoInfer<A>) => B
): (self: ReadonlyArray<A>) => Array<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }>
<N extends string, A extends object, B>(
self: ReadonlyArray<A>,
tag: Exclude<N, keyof A>,
f: (a: A) => B
f: (a: NoInfer<A>) => B
): Array<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }>
} = doNotation.let_<ReadonlyArrayTypeLambda>(map) as any

Expand Down
12 changes: 6 additions & 6 deletions packages/effect/src/Effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3558,12 +3558,12 @@ export const Do: Effect<{}> = effect.Do
export const bind: {
<N extends string, A extends object, B, E2, R2>(
name: Exclude<N, keyof A>,
f: (a: A) => Effect<B, E2, R2>
f: (a: NoInfer<A>) => Effect<B, E2, R2>
): <E1, R1>(self: Effect<A, E1, R1>) => Effect<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E2 | E1, R2 | R1>
<A extends object, N extends string, E1, R1, B, E2, R2>(
self: Effect<A, E1, R1>,
name: Exclude<N, keyof A>,
f: (a: A) => Effect<B, E2, R2>
f: (a: NoInfer<A>) => Effect<B, E2, R2>
): Effect<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E1 | E2, R1 | R2>
} = effect.bind

Expand Down Expand Up @@ -3599,7 +3599,7 @@ export const bindAll: {
readonly concurrentFinalizers?: boolean | undefined
}
>(
f: (a: A) => [Extract<keyof X, keyof A>] extends [never] ? X : `Duplicate keys`,
f: (a: NoInfer<A>) => [Extract<keyof X, keyof A>] extends [never] ? X : `Duplicate keys`,
options?: undefined | O
): <E1, R1>(
self: Effect<A, E1, R1>
Expand All @@ -3623,7 +3623,7 @@ export const bindAll: {
R1
>(
self: Effect<A, E1, R1>,
f: (a: A) => [Extract<keyof X, keyof A>] extends [never] ? X : `Duplicate keys`,
f: (a: NoInfer<A>) => [Extract<keyof X, keyof A>] extends [never] ? X : `Duplicate keys`,
options?: undefined | {
readonly concurrency?: Concurrency | undefined
readonly batching?: boolean | "inherit" | undefined
Expand Down Expand Up @@ -3675,12 +3675,12 @@ export const bindTo: {
const let_: {
<N extends string, A extends object, B>(
name: Exclude<N, keyof A>,
f: (a: A) => B
f: (a: NoInfer<A>) => B
): <E, R>(self: Effect<A, E, R>) => Effect<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E, R>
<A extends object, N extends string, E, R, B>(
self: Effect<A, E, R>,
name: Exclude<N, keyof A>,
f: (a: A) => B
f: (a: NoInfer<A>) => B
): Effect<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E, R>
} = effect.let_

Expand Down
8 changes: 4 additions & 4 deletions packages/effect/src/Either.ts
Original file line number Diff line number Diff line change
Expand Up @@ -851,12 +851,12 @@ export const Do: Either<{}> = right({})
export const bind: {
<N extends string, A extends object, B, L2>(
name: Exclude<N, keyof A>,
f: (a: A) => Either<B, L2>
f: (a: NoInfer<A>) => Either<B, L2>
): <L1>(self: Either<A, L1>) => Either<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, L1 | L2>
<A extends object, L1, N extends string, B, L2>(
self: Either<A, L1>,
name: Exclude<N, keyof A>,
f: (a: A) => Either<B, L2>
f: (a: NoInfer<A>) => Either<B, L2>
): Either<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, L1 | L2>
} = doNotation.bind<EitherTypeLambda>(map, flatMap)

Expand Down Expand Up @@ -896,12 +896,12 @@ export const bindTo: {
const let_: {
<N extends string, R extends object, B>(
name: Exclude<N, keyof R>,
f: (r: R) => B
f: (r: NoInfer<R>) => B
): <L>(self: Either<R, L>) => Either<{ [K in N | keyof R]: K extends keyof R ? R[K] : B }, L>
<R extends object, L, N extends string, B>(
self: Either<R, L>,
name: Exclude<N, keyof R>,
f: (r: R) => B
f: (r: NoInfer<R>) => B
): Either<{ [K in N | keyof R]: K extends keyof R ? R[K] : B }, L>
} = doNotation.let_<EitherTypeLambda>(map)

Expand Down
8 changes: 4 additions & 4 deletions packages/effect/src/Micro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3662,24 +3662,24 @@ export const bindTo: {
export const bind: {
<N extends string, A extends Record<string, any>, B, E2, R2>(
name: N,
f: (a: A) => Micro<B, E2, R2>
f: (a: NoInfer<A>) => Micro<B, E2, R2>
): <E, R>(self: Micro<A, E, R>) => Micro<Simplify<Omit<A, N> & { [K in N]: B }>, E | E2, R | R2>
<A extends Record<string, any>, E, R, B, E2, R2, N extends string>(
self: Micro<A, E, R>,
name: N,
f: (a: A) => Micro<B, E2, R2>
f: (a: NoInfer<A>) => Micro<B, E2, R2>
): Micro<Simplify<Omit<A, N> & { [K in N]: B }>, E | E2, R | R2>
} = doNotation.bind<MicroTypeLambda>(map, flatMap)

const let_: {
<N extends string, A extends Record<string, any>, B>(
name: N,
f: (a: A) => B
f: (a: NoInfer<A>) => B
): <E, R>(self: Micro<A, E, R>) => Micro<Simplify<Omit<A, N> & { [K in N]: B }>, E, R>
<A extends Record<string, any>, E, R, B, N extends string>(
self: Micro<A, E, R>,
name: N,
f: (a: A) => B
f: (a: NoInfer<A>) => B
): Micro<Simplify<Omit<A, N> & { [K in N]: B }>, E, R>
} = doNotation.let_<MicroTypeLambda>(map)

Expand Down
8 changes: 4 additions & 4 deletions packages/effect/src/Option.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1233,12 +1233,12 @@ export const bindTo: {
const let_: {
<N extends string, A extends object, B>(
name: Exclude<N, keyof A>,
f: (a: A) => B
f: (a: NoInfer<A>) => B
): (self: Option<A>) => Option<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }>
<A extends object, N extends string, B>(
self: Option<A>,
name: Exclude<N, keyof A>,
f: (a: A) => B
f: (a: NoInfer<A>) => B
): Option<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }>
} = doNotation.let_<OptionTypeLambda>(map)

Expand Down Expand Up @@ -1309,12 +1309,12 @@ export {
export const bind: {
<N extends string, A extends object, B>(
name: Exclude<N, keyof A>,
f: (a: A) => Option<B>
f: (a: NoInfer<A>) => Option<B>
): (self: Option<A>) => Option<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }>
<A extends object, N extends string, B>(
self: Option<A>,
name: Exclude<N, keyof A>,
f: (a: A) => Option<B>
f: (a: NoInfer<A>) => Option<B>
): Option<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }>
} = doNotation.bind<OptionTypeLambda>(map, flatMap)

Expand Down
8 changes: 4 additions & 4 deletions packages/effect/src/STM.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2010,24 +2010,24 @@ export const Do: STM<{}> = succeed({})
export const bind: {
<N extends string, K, A, E2, R2>(
tag: Exclude<N, keyof K>,
f: (_: K) => STM<A, E2, R2>
f: (_: NoInfer<K>) => STM<A, E2, R2>
): <E, R>(self: STM<K, E, R>) => STM<MergeRecord<K, { [k in N]: A }>, E2 | E, R2 | R>
<K, E, R, N extends string, A, E2, R2>(
self: STM<K, E, R>,
tag: Exclude<N, keyof K>,
f: (_: K) => STM<A, E2, R2>
f: (_: NoInfer<K>) => STM<A, E2, R2>
): STM<MergeRecord<K, { [k in N]: A }>, E | E2, R | R2>
} = stm.bind

const let_: {
<N extends string, K, A>(
tag: Exclude<N, keyof K>,
f: (_: K) => A
f: (_: NoInfer<K>) => A
): <E, R>(self: STM<K, E, R>) => STM<MergeRecord<K, { [k in N]: A }>, E, R>
<K, E, R, N extends string, A>(
self: STM<K, E, R>,
tag: Exclude<N, keyof K>,
f: (_: K) => A
f: (_: NoInfer<K>) => A
): STM<MergeRecord<K, { [k in N]: A }>, E, R>
} = stm.let_

Expand Down
24 changes: 10 additions & 14 deletions packages/effect/src/Stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5996,15 +5996,15 @@ export const Do: Stream<{}> = internal.Do
export const bind: {
<N extends string, A, B, E2, R2>(
tag: Exclude<N, keyof A>,
f: (_: A) => Stream<B, E2, R2>,
f: (_: NoInfer<A>) => Stream<B, E2, R2>,
options?:
| { readonly concurrency?: number | "unbounded" | undefined; readonly bufferSize?: number | undefined }
| undefined
): <E, R>(self: Stream<A, E, R>) => Stream<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E2 | E, R2 | R>
<A, E, R, N extends string, B, E2, R2>(
self: Stream<A, E, R>,
tag: Exclude<N, keyof A>,
f: (_: A) => Stream<B, E2, R2>,
f: (_: NoInfer<A>) => Stream<B, E2, R2>,
options?:
| { readonly concurrency?: number | "unbounded" | undefined; readonly bufferSize?: number | undefined }
| undefined
Expand All @@ -6025,19 +6025,15 @@ export const bind: {
export const bindEffect: {
<N extends string, A, B, E2, R2>(
tag: Exclude<N, keyof A>,
f: (_: A) => Effect.Effect<B, E2, R2>,
options?:
| { readonly concurrency?: number | "unbounded" | undefined; readonly bufferSize?: number | undefined }
| undefined
): <E, R>(self: Stream<A, E, R>) => Stream<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E2 | E, R2 | R>
f: (_: NoInfer<A>) => Effect.Effect<B, E2, R2>,
options?: { readonly concurrency?: number | "unbounded" | undefined; readonly bufferSize?: number | undefined }
): <E, R>(self: Stream<A, E, R>) => Stream<{ [K in keyof A | N]: K extends keyof A ? A[K] : B }, E | E2, R | R2>
<A, E, R, N extends string, B, E2, R2>(
self: Stream<A, E, R>,
tag: Exclude<N, keyof A>,
f: (_: A) => Effect.Effect<B, E2, R2>,
options?:
| { readonly concurrency?: number | "unbounded" | undefined; readonly unordered?: boolean | undefined }
| undefined
): Stream<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E | E2, R | R2>
f: (_: NoInfer<A>) => Effect.Effect<B, E2, R2>,
options?: { readonly concurrency?: number | "unbounded" | undefined; readonly unordered?: boolean | undefined }
): Stream<{ [K in keyof A | N]: K extends keyof A ? A[K] : B }, E | E2, R | R2>
} = _groupBy.bindEffect

/**
Expand Down Expand Up @@ -6077,12 +6073,12 @@ export const bindTo: {
const let_: {
<N extends string, A extends object, B>(
name: Exclude<N, keyof A>,
f: (a: A) => B
f: (a: NoInfer<A>) => B
): <E, R>(self: Stream<A, E, R>) => Stream<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E, R>
<A extends object, E, R, N extends string, B>(
self: Stream<A, E, R>,
name: Exclude<N, keyof A>,
f: (a: A) => B
f: (a: NoInfer<A>) => B
): Stream<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E, R>
} = internal.let_

Expand Down
8 changes: 4 additions & 4 deletions packages/effect/src/internal/core-effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -375,14 +375,14 @@ export const Do: Effect.Effect<{}> = core.succeed({})
export const bind: {
<N extends string, A extends object, B, E2, R2>(
name: Exclude<N, keyof A>,
f: (a: A) => Effect.Effect<B, E2, R2>
f: (a: NoInfer<A>) => Effect.Effect<B, E2, R2>
): <E1, R1>(
self: Effect.Effect<A, E1, R1>
) => Effect.Effect<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E2 | E1, R2 | R1>
<A extends object, N extends string, E1, R1, B, E2, R2>(
self: Effect.Effect<A, E1, R1>,
name: Exclude<N, keyof A>,
f: (a: A) => Effect.Effect<B, E2, R2>
f: (a: NoInfer<A>) => Effect.Effect<B, E2, R2>
): Effect.Effect<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E1 | E2, R1 | R2>
} = doNotation.bind<Effect.EffectTypeLambda>(core.map, core.flatMap)

Expand All @@ -396,14 +396,14 @@ export const bindTo: {
export const let_: {
<N extends string, A extends object, B>(
name: Exclude<N, keyof A>,
f: (a: A) => B
f: (a: NoInfer<A>) => B
): <E, R>(
self: Effect.Effect<A, E, R>
) => Effect.Effect<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E, R>
<A extends object, N extends string, E, R, B>(
self: Effect.Effect<A, E, R>,
name: Exclude<N, keyof A>,
f: (a: A) => B
f: (a: NoInfer<A>) => B
): Effect.Effect<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E, R>
} = doNotation.let_<Effect.EffectTypeLambda>(core.map)

Expand Down
13 changes: 7 additions & 6 deletions packages/effect/src/internal/doNotation.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { NoInfer } from "effect/Types"
import { dual } from "../Function.js"
import type { Kind, TypeLambda } from "../HKT.js"

Expand All @@ -22,20 +23,20 @@ export const let_ = <F extends TypeLambda>(
): {
<N extends string, A extends object, B>(
name: Exclude<N, keyof A>,
f: (a: A) => B
f: (a: NoInfer<A>) => B
): <R, O, E>(
self: Kind<F, R, O, E, A>
) => Kind<F, R, O, E, { [K in keyof A | N]: K extends keyof A ? A[K] : B }>
<R, O, E, A extends object, N extends string, B>(
self: Kind<F, R, O, E, A>,
name: Exclude<N, keyof A>,
f: (a: A) => B
f: (a: NoInfer<A>) => B
): Kind<F, R, O, E, { [K in keyof A | N]: K extends keyof A ? A[K] : B }>
} =>
dual(3, <R, O, E, A extends object, N extends string, B>(
self: Kind<F, R, O, E, A>,
name: Exclude<N, keyof A>,
f: (a: A) => B
f: (a: NoInfer<A>) => B
): Kind<F, R, O, E, { [K in keyof A | N]: K extends keyof A ? A[K] : B }> =>
map(self, (a) => Object.assign({}, a, { [name]: f(a) }) as any))

Expand All @@ -58,20 +59,20 @@ export const bindTo = <F extends TypeLambda>(map: Map<F>): {
export const bind = <F extends TypeLambda>(map: Map<F>, flatMap: FlatMap<F>): {
<N extends string, A extends object, R2, O2, E2, B>(
name: Exclude<N, keyof A>,
f: (a: A) => Kind<F, R2, O2, E2, B>
f: (a: NoInfer<A>) => Kind<F, R2, O2, E2, B>
): <R1, O1, E1>(
self: Kind<F, R1, O1, E1, A>
) => Kind<F, R1 & R2, O1 | O2, E1 | E2, { [K in keyof A | N]: K extends keyof A ? A[K] : B }>
<R1, O1, E1, A extends object, N extends string, R2, O2, E2, B>(
self: Kind<F, R1, O1, E1, A>,
name: Exclude<N, keyof A>,
f: (a: A) => Kind<F, R2, O2, E2, B>
f: (a: NoInfer<A>) => Kind<F, R2, O2, E2, B>
): Kind<F, R1 & R2, O1 | O2, E1 | E2, { [K in keyof A | N]: K extends keyof A ? A[K] : B }>
} =>
dual(3, <R1, O1, E1, A, N extends string, R2, O2, E2, B>(
self: Kind<F, R1, O1, E1, A>,
name: Exclude<N, keyof A>,
f: (a: A) => Kind<F, R2, O2, E2, B>
f: (a: NoInfer<A>) => Kind<F, R2, O2, E2, B>
): Kind<F, R1 & R2, O1 | O2, E1 | E2, { [K in keyof A | N]: K extends keyof A ? A[K] : B }> =>
flatMap(self, (a) =>
map(f(a), (b) => Object.assign({}, a, { [name]: b }) as { [K in keyof A | N]: K extends keyof A ? A[K] : B })))
4 changes: 2 additions & 2 deletions packages/effect/src/internal/groupBy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ export const mapEffectOptions = dual<
export const bindEffect = dual<
<N extends string, A, B, E2, R2>(
tag: Exclude<N, keyof A>,
f: (_: A) => Effect.Effect<B, E2, R2>,
f: (_: NoInfer<A>) => Effect.Effect<B, E2, R2>,
options?: {
readonly concurrency?: number | "unbounded" | undefined
readonly bufferSize?: number | undefined
Expand All @@ -290,7 +290,7 @@ export const bindEffect = dual<
<A, E, R, N extends string, B, E2, R2>(
self: Stream.Stream<A, E, R>,
tag: Exclude<N, keyof A>,
f: (_: A) => Effect.Effect<B, E2, R2>,
f: (_: NoInfer<A>) => Effect.Effect<B, E2, R2>,
options?: {
readonly concurrency?: number | "unbounded" | undefined
readonly unordered?: boolean | undefined
Expand Down
Loading

0 comments on commit 61a99b2

Please sign in to comment.