Hyperlinkv0.8.0-beta.28

Channel

Channel.scanEffectconsteffect/Channel.ts:3802
<S, OutElem, E, R>(
  initial: S,
  f: (s: S, a: Types.NoInfer<OutElem>) => Effect.Effect<S, E, R>
): <OutErr, OutDone, InElem, InErr, InDone, Env>(
  self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>
) => Channel<S, OutErr | E, OutDone, InElem, InErr, InDone, Env | R>
<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, S, E, R>(
  self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>,
  initial: S,
  f: (s: S, a: Types.NoInfer<OutElem>) => Effect.Effect<S, E, R>
): Channel<S, OutErr | E, OutDone, InElem, InErr, InDone, Env | R>

Transforms a channel statefully by scanning over its output with an effectful accumulator function. Emits the intermediate results of the scan operation.

When to use

Use when maintaining accumulated state over channel output requires Effects or can fail, while still emitting each intermediate state.

Example (Scanning channel output with effects)

import { Channel, Data, Effect } from "effect"

class ScanError extends Data.TaggedError("ScanError")<{
  readonly reason: string
}> {}

// Create a channel with numbers
const numbersChannel = Channel.fromIterable([1, 2, 3, 4])

// Effectful scan with async operations
const asyncScanChannel = Channel.scanEffect(
  numbersChannel,
  "",
  (acc, value) =>
    Effect.gen(function*() {
      // Simulate async work
      yield* Effect.sleep("10 millis")
      return acc + value.toString()
    })
)
// Outputs: "", "1", "12", "123", "1234"

// Scan with error handling
const errorHandlingScan = Channel.scanEffect(
  numbersChannel,
  0,
  (sum, n) => {
    if (n < 0) {
      return Effect.fail(new ScanError({ reason: "negative number" }))
    }
    return Effect.succeed(sum + n)
  }
)
sequencing
Source effect/Channel.ts:380246 lines
export const scanEffect: {
  <S, OutElem, E, R>(initial: S, f: (s: S, a: Types.NoInfer<OutElem>) => Effect.Effect<S, E, R>): <
    OutErr,
    OutDone,
    InElem,
    InErr,
    InDone,
    Env
  >(self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>) => Channel<
    S,
    OutErr | E,
    OutDone,
    InElem,
    InErr,
    InDone,
    Env | R
  >
  <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, S, E, R>(
    self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>,
    initial: S,
    f: (s: S, a: Types.NoInfer<OutElem>) => Effect.Effect<S, E, R>
  ): Channel<S, OutErr | E, OutDone, InElem, InErr, InDone, Env | R>
} = dual(3, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, S, E, R>(
  self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>,
  initial: S,
  f: (s: S, a: Types.NoInfer<OutElem>) => Effect.Effect<S, E, R>
): Channel<S, OutErr | E, OutDone, InElem, InErr, InDone, Env | R> =>
  fromTransform((upstream, scope) =>
    Effect.map(toTransform(self)(upstream, scope), (pull) => {
      let state = initial
      let isFirst = true
      return Effect.suspend(() => {
        if (isFirst) {
          isFirst = false
          return Effect.succeed(state)
        }
        return Effect.map(
          Effect.flatMap(pull, (a) => f(state, a)),
          (newState) => {
            state = newState
            return state
          }
        )
      })
    })
  ))
Referenced by 2 symbols