Skip to content

[Repo Assist] Add AsyncSeq.sortByAsync and sortByDescendingAsync#285

Draft
github-actions[bot] wants to merge 2 commits intomainfrom
repo-assist/improve-sortbyasync-2026-03-19-33a292cbfa6ee355
Draft

[Repo Assist] Add AsyncSeq.sortByAsync and sortByDescendingAsync#285
github-actions[bot] wants to merge 2 commits intomainfrom
repo-assist/improve-sortbyasync-2026-03-19-33a292cbfa6ee355

Conversation

@github-actions
Copy link
Contributor

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

Summary

Adds two new async sort functions that fill a small gap in the AsyncSeq API and are consistent with the existing *Async pattern established by minByAsync, maxByAsync, countByAsync, and sumByAsync.

Function Description Pattern
sortByAsync Sorts by an asynchronous key projection; returns Async(array<'T)> minByAsync / maxByAsync
sortByDescendingAsync Same as above but in descending key order sortByDescending sync twin

Motivation

AsyncSeq already has sortBy (sync projection) and sortByDescending. The common *Async twins for projection-based operations (minByAsync, maxByAsync, countByAsync, sumByAsync) are all present. sortByAsync / sortByDescendingAsync were the only obvious gap.

Use case example: ordering query results by an async-computed property (e.g. a cached value fetched from a remote store):

let sorted =
    entities
    |> AsyncSeq.sortByAsync (fun e -> fetchScore e.Id)   // Async(int)
    |> Async.RunSynchronously

Implementation

Both functions use mapAsync to pair each element with its projection key (computing the key exactly once), then toArrayAsync to materialise, then a standard Array.sort* call:

let sortByAsync projection source = async {
    let! pairs =
        source
        |> mapAsync (fun x -> async { let! k = projection x in return (k, x) })
        |> toArrayAsync
    return pairs |> Array.sortBy fst |> Array.map snd }

Changes

  • src/FSharp.Control.AsyncSeq/AsyncSeq.fs — 2 new function implementations
  • src/FSharp.Control.AsyncSeq/AsyncSeq.fsi — 2 new public signatures with XML-doc
  • tests/FSharp.Control.AsyncSeq.Tests/AsyncSeqTests.fs — 5 new tests
  • RELEASE_NOTES.md — 4.10.1 entry

New Tests

Test What it checks
sortByAsync sorts ascending by async projection Correct ascending order by string length
sortByAsync returns empty array for empty sequence Edge case — empty input
sortByAsync computes projection exactly once per element No redundant projection calls
sortByDescendingAsync sorts descending by async projection Correct descending order
sortByDescendingAsync returns empty array for empty sequence Edge case — empty input

Test Status

✅ Build succeeded (0 errors, pre-existing warnings only — NU1605, FS9999 for groupByAsync).

✅ All 326 tests pass — 5 new, 321 pre-existing.

Generated by Repo Assist ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@346204513ecfa08b81566450d7d599556807389f

Adds two new async sorting functions that mirror the existing 'Async' variants
pattern of minByAsync, maxByAsync, and countByAsync:

- sortByAsync: sorts by an async key projection, returning Async<array<'T>>
- sortByDescendingAsync: same but in descending order

Both functions compute each key exactly once per element, then sort.
5 new tests added; all 326 tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

0 participants