Skip to content

Comments

[Repo Assist] Add AsyncSeq.reduce and AsyncSeq.reduceAsync#242

Merged
dsyme merged 1 commit intomainfrom
repo-assist/improve-reduce-20260223-0d292d21077d1b0c
Feb 24, 2026
Merged

[Repo Assist] Add AsyncSeq.reduce and AsyncSeq.reduceAsync#242
dsyme merged 1 commit intomainfrom
repo-assist/improve-reduce-20260223-0d292d21077d1b0c

Conversation

@github-actions
Copy link
Contributor

🤖 This PR was created by Repo Assist, an automated AI assistant.


Summary

Adds two new aggregation combinators that mirror Seq.reduce:

AsyncSeq.reduce    : reduction:('T -> 'T -> 'T)          -> source:AsyncSeq<'T> -> Async<'T>
AsyncSeq.reduceAsync : reduction:('T -> 'T -> Async<'T>) -> source:AsyncSeq<'T> -> Async<'T>

Usage:

// Sum an async sequence without an initial state
let! total = asyncSeq { yield 1; yield 2; yield 3 } |> AsyncSeq.reduce (+)
// total = 6

// Custom async reduction
let! result =
    asyncSeq { yield "hello"; yield " "; yield "world" }
    |> AsyncSeq.reduceAsync (fun a b -> async { return a + b })
// result = "hello world"

Motivation

Seq.reduce is a standard F# function that is commonly used when no natural "zero" element exists (e.g. max, string concatenation, non-commutative operations). Its absence from AsyncSeq is a minor but consistent API gap. fold/foldAsync can work around it by passing the first element as the state, but that's awkward and easy to get wrong.

Implementation

  • reduceAsync consumes the internal pull-based enumerator directly, yielding the first element as the initial accumulator.
  • reduce delegates to reduceAsync (same pattern as fold/foldAsync).
  • Raises InvalidOperationException("The input sequence was empty.") when the source is empty, matching Seq.reduce semantics.

Test Status

✅ All 199 tests pass (dotnet test). 5 new tests cover:

  1. Non-empty sequence sums correctly
  2. Single-element sequence returns that element unchanged
  3. Empty sequence raises InvalidOperationException
  4. Async reduction function works correctly
  5. Results match Seq.reduce across multiple input sizes

Generated by Repo Assist

To install this workflow, run gh aw add githubnext/agentics/workflows/repo-assist.md@2f03fdaafb8c1ae62dfde7e0be762a822a201aeb. View source at https://github.com/githubnext/agentics/tree/2f03fdaafb8c1ae62dfde7e0be762a822a201aeb/workflows/repo-assist.md.

Adds two new combinators:
- reduce: ('T -> 'T -> 'T) -> AsyncSeq<'T> -> Async<'T>
- reduceAsync: ('T -> 'T -> Async<'T>) -> AsyncSeq<'T> -> Async<'T>

These mirror Seq.reduce: aggregate without an initial state, raising
InvalidOperationException on empty sequences. reduce is implemented
in terms of reduceAsync for consistency.

5 new tests added covering: non-empty sequences, single-element sequences,
empty sequence exception, async reduction, and parity with Seq.reduce.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Contributor Author

Pull request created: #242

@dsyme dsyme marked this pull request as ready for review February 24, 2026 02:19
@dsyme dsyme closed this Feb 24, 2026
@dsyme dsyme reopened this Feb 24, 2026
@dsyme dsyme merged commit 7e95dcc into main Feb 24, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant