Minor Changes
-
#2006
96bcee2
Thanks @github-actions! - changeRuntime.AsyncFiberException
type parameters order fromAsyncFiberException<E, A>
toAsyncFiberException<A, E = never>
-
#2006
96bcee2
Thanks @github-actions! - changeRuntime.Cancel
type parameters order fromCancel<E, A>
toCancel<A, E = never>
-
#2006
c77f635
Thanks @github-actions! - changeExit
type parameter order fromExit<E, A>
toExit<A, E = never>
-
#2006
e343a74
Thanks @github-actions! - changeResource
type parameters order fromResource<E, A>
toResource<A, E = never>
-
#2006
acf1894
Thanks @github-actions! - changeFiberMap
type parameters order fromFiberMap<K, E = unknown, A = unknown>
toFiberMap<K, A = unknown, E = unknown>
-
#2006
9a2d1c1
Thanks @github-actions! - With this change we now require a string key to be provided for all tags and renames the dear oldTag
toGenericTag
, so when previously you could do:import { Effect, Context } from "effect"; interface Service { readonly _: unique symbol; } const Service = Context.Tag< Service, { number: Effect.Effect<never, never, number>; } >();
you are now mandated to do:
import { Effect, Context } from "effect"; interface Service { readonly _: unique symbol; } const Service = Context.GenericTag< Service, { number: Effect.Effect<never, never, number>; } >("Service");
This makes by default all tags globals and ensures better debuggaility when unexpected errors arise.
Furthermore we introduce a new way of constructing tags that should be considered the new default:
import { Effect, Context } from "effect"; class Service extends Context.Tag("Service")< Service, { number: Effect.Effect<never, never, number>; } >() {} const program = Effect.flatMap(Service, ({ number }) => number).pipe( Effect.flatMap((_) => Effect.log(`number: ${_}`)), );
this will use "Service" as the key and will create automatically an opaque identifier (the class) to be used at the type level, it does something similar to the above in a single shot.
-
#2006
1a77f72
Thanks @github-actions! - changeEffect
type parameters order fromEffect<R, E, A>
toEffect<A, E = never, R = never>
-
#2006
c986f0e
Thanks @github-actions! - changeFiberSet
type parameters order fromFiberSet<E, A>
toFiberSet<A, E = never>
-
#2006
96bcee2
Thanks @github-actions! - changeRuntime.RunCallbackOptions
type parameters order fromRunCallbackOptions<E, A>
toRunCallbackOptions<A, E = never>
-
#2006
70dde23
Thanks @github-actions! - changeTDeferred
type parameters order fromTDeferred<E, A>
toTDeferred<A, E = never>
-
#2006
81b7425
Thanks @github-actions! - changeStreamable.Class
andEffectable.Class
type parameters order fromClass<R, E, A>
toClass<A, E = never, R = never>
-
#2006
02c3461
Thanks @github-actions! - With this change we remove theData.Data
type and we makeEqual.Equal
&Hash.Hash
implicit traits.The main reason is that
Data.Data<A>
was structurally equivalent toA & Equal.Equal
but extendingEqual.Equal
doesn't mean that the equality is implemented by-value, so the type was simply adding noise without gaining any level of safety.The module
Data
remains unchanged at the value level, all the functions previously available are supposed to work in exactly the same manner.At the type level instead the functions return
Readonly
variants, so for example we have:import { Data } from "effect"; const obj = Data.struct({ a: 0, b: 1, });
will have the
obj
typed as:declare const obj: { readonly a: number; readonly b: number; };
-
#2006
0e56e99
Thanks @github-actions! - changeDeferred
type parameters order fromDeferred<E, A>
toDeferred<A, E>
-
#2006
8b0ded9
Thanks @github-actions! - changeFiber
type parameters order fromFiber<E, A>
toFiber<A, E = never>
-
#2006
8dd83e8
Thanks @github-actions! - changeChannel
type parameters order fromChannel<out Env, in InErr, in InElem, in InDone, out OutErr, out OutElem, out OutDone>
toChannel<OutElem, InElem = unknown, OutErr = never, InErr = unknown, OutDone = void, InDone = unknown, Env = never>
-
#2006
d75f6fe
Thanks @github-actions! - changeTake
type parameters order fromTake<E, A>
toTake<A, E = never>
-
#2006
7356e5c
Thanks @github-actions! - changeSTM
type parameters order fromSTM<R, E, A>
toSTM<A, E = never, R = never>
-
#2006
3077cde
Thanks @github-actions! - changeStream
type parameters order fromStream<R, E, A>
toStream<A, E = never, R = never>
-
#2006
78f47ab
Thanks @github-actions! - changePool
type parameters order fromPool<E, A>
toPool<A, E = never>
, andKeyedPool
fromKeyedPool<E, A>
toKeyedPool<A, E = never>
-
#2006
52e5d20
Thanks @github-actions! - changeRequest
type parameters order fromRequest<E, A>
toRequest<A, E = never>
-
#2006
c6137ec
Thanks @github-actions! - changeRuntimeFiber
type parameters order fromRuntimeFiber<E, A>
toRuntimeFiber<A, E = never>
-
#2006
f5ae081
Thanks @github-actions! - UseTimeoutException
instead ofNoSuchElementException
for timeout. -
#2006
60686f5
Thanks @github-actions! - changeLayer
type parameters order fromLayer<RIn, E, ROut>
toLayer<ROut, E = never, RIn = never>
-
#2006
9a2d1c1
Thanks @github-actions! - This change enablesEffect.serviceConstants
andEffect.serviceMembers
to access any constant in the service, not only the effects, namely it is now possible to do:import { Effect, Context } from "effect"; class NumberRepo extends Context.TagClass("NumberRepo")< NumberRepo, { readonly numbers: Array<number>; } >() { static numbers = Effect.serviceConstants(NumberRepo).numbers; }
-
#2006
5127afe
Thanks @github-actions! - Rename ReadonlyRecord.update to .replace -
#2006
8ee2931
Thanks @github-actions! - enhance DX by swapping type parameters and adding defaults to:- Effect
- async
- asyncOption
- asyncEither
- Stream
- asyncEffect
- asyncInterrupt
- asyncOption
- asyncScoped
- identity
- Effect
-
#2006
6727474
Thanks @github-actions! - changeSink
type parameters order fromSink<out R, out E, in In, out L, out Z>
toSink<out A, in In = unknown, out L = never, out E = never, out R = never>
-
#2006
5127afe
Thanks @github-actions! - rename ReadonlyRecord.upsert to .set
Patch Changes
-
#2006
5127afe
Thanks @github-actions! - add ReadonlyRecord.modify -
#2083
be19ce0
Thanks @mikearnaldi! - AddRatelimiter
which limits the number of calls to a resource within a time window using the token bucket algorithm.Usage Example:
import { Effect, RateLimiter } from "effect"; // we need a scope because the rate limiter needs to allocate a state and a background job const program = Effect.scoped( Effect.gen(function* ($) { // create a rate limiter that executes up to 10 requests within 2 seconds const rateLimit = yield* $(RateLimiter.make(10, "2 seconds")); // simulate repeated calls for (let n = 0; n < 100; n++) { // wrap the effect we want to limit with rateLimit yield* $(rateLimit(Effect.log("Calling RateLimited Effect"))); } }), ); // will print 10 calls immediately and then throttle program.pipe(Effect.runFork);
Or, in a more real world scenario, with a dedicated Service + Layer:
import { Context, Effect, Layer, RateLimiter } from "effect"; class ApiLimiter extends Context.Tag("@services/ApiLimiter")< ApiLimiter, RateLimiter.RateLimiter >() { static Live = RateLimiter.make(10, "2 seconds").pipe( Layer.scoped(ApiLimiter), ); } const program = Effect.gen(function* ($) { const rateLimit = yield* $(ApiLimiter); for (let n = 0; n < 100; n++) { yield* $(rateLimit(Effect.log("Calling RateLimited Effect"))); } }); program.pipe(Effect.provide(ApiLimiter.Live), Effect.runFork);
-
#2084
4a5d01a
Thanks @tim-smart! - simplify RateLimiter implementation using semaphore -
#2084
4a5d01a
Thanks @tim-smart! - add Number.nextPow2This function returns the next power of 2 from the given number.
import { nextPow2 } from "effect/Number"; assert.deepStrictEqual(nextPow2(5), 8); assert.deepStrictEqual(nextPow2(17), 32);