Skip to content

[Repo Assist] feat: add TaskSeq.distinctUntilChangedWith and distinctUntilChangedWithAsync#346

Draft
github-actions[bot] wants to merge 2 commits intomainfrom
repo-assist/fix-issue-345-distinctUntilChangedWith-8aef3b6a9525a64a
Draft

[Repo Assist] feat: add TaskSeq.distinctUntilChangedWith and distinctUntilChangedWithAsync#346
github-actions[bot] wants to merge 2 commits intomainfrom
repo-assist/fix-issue-345-distinctUntilChangedWith-8aef3b6a9525a64a

Conversation

@github-actions
Copy link
Contributor

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

Summary

Adds two new functions that extend TaskSeq.distinctUntilChanged with a caller-supplied equality predicate:

TaskSeq.distinctUntilChangedWith      : ('T -> 'T -> bool)        -> TaskSeq<'T> -> TaskSeq<'T>
TaskSeq.distinctUntilChangedWithAsync : ('T -> 'T -> #Task(bool)) -> TaskSeq<'T> -> TaskSeq<'T>

Both yield elements from the source, skipping any element that compares equal to its predecessor according to the supplied comparer — exactly like distinctUntilChanged but with a custom equality function instead of structural (=).

Motivation

This is one of the "Group 1" additions identified in the AsyncSeq/TaskSeq design-parity gap analysis (issue #345). FSharp.Control.AsyncSeq has distinctUntilChangedWith / distinctUntilChangedWithAsync and these are a natural extension to the existing distinctUntilChanged.

Use cases:

  • Case-insensitive deduplication: distinctUntilChangedWith (fun a b -> String.Equals(a, b, StringComparison.OrdinalIgnoreCase))
  • Fuzzy numeric comparison: distinctUntilChangedWith (fun a b -> abs (a - b) <= tolerance)
  • Projected equality: compare on a field without materialising a key sequence

Changes

File Change
TaskSeqInternal.fs Added distinctUntilChangedWith and distinctUntilChangedWithAsync
TaskSeq.fs Added two static dispatch members
TaskSeq.fsi Added XML-documented signatures
TaskSeq.DistinctUntilChanged.Tests.fs 40 new tests (63 total in the file)
release-notes.txt Updated under 1.0.0

Trade-offs

  • No 'T: equality constraint on the With variants — the caller supplies the equality function, so no structural equality constraint is needed. This is intentional and consistent with how distinctBy works.
  • The async variant's comparer type is 'T -> 'T -> #Task(bool), following the same pattern as distinctByAsync and other async overloads in the library.

Test Status

✅ Build: dotnet build src/FSharp.Control.TaskSeq.sln -c Releasesucceeded, 0 warnings, 0 errors
✅ Format: dotnet fantomas . --checkall files correctly formatted
✅ Tests: dotnet test ... -c Release4,741 passed, 2 skipped (infrastructure), 0 failed

Relates to #345.

Generated by Repo Assist ·

To install this agentic workflow, run

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

…thAsync

Adds two new functions that extend the existing distinctUntilChanged
with a user-supplied comparer predicate:

- TaskSeq.distinctUntilChangedWith: ('T -> 'T -> bool) -> TaskSeq<'T> -> TaskSeq<'T>
- TaskSeq.distinctUntilChangedWithAsync: ('T -> 'T -> #Task<bool>) -> TaskSeq<'T> -> TaskSeq<'T>

Both functions yield elements from the source, skipping any element
that compares equal to its predecessor according to the supplied
comparer. They mirror the existing distinctUntilChanged but give
callers control over equality (e.g. case-insensitive strings, fuzzy
numeric comparison, projected keys).

Includes 40 new tests (63 total in the DistinctUntilChanged test file).
All 4,741 tests pass.

Relates to #345

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