Repository navigation
feat: add FSharp.Azure.Cosmos.Sql with EquatableArray and the ImmutableArray patterns - #48
Open
xperiandri wants to merge 1 commit into
Open
xperiandri wants to merge 1 commit into
xperiandri wants to merge 1 commit into
Conversation
4 of 6 tasks
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
The focused implementation, documentation, project integration, and tests are consistent and complete.
0 open findings
What changed in this PR
Introduces the foundational collection helpers and project structure for the forthcoming Cosmos SQL model.
Changes:
- Adds structurally equatable immutable arrays and allocation-free
ImmutableArrayactive patterns. - Adds comprehensive emulator-free MSTest coverage.
- Registers the new library and test projects in the solution.
| File | Description |
|---|---|
.github/copilot-instructions.md |
Documents the new project structure. |
FSharp.Azure.Cosmos.slnf |
Adds projects to the solution filter. |
FSharp.Azure.Cosmos.slnx |
Adds projects to the solution. |
src/Cosmos.Sql/AssemblyInfo.fs |
Defines generated assembly metadata. |
src/Cosmos.Sql/EquatableArray.fs |
Implements structural immutable arrays. |
src/Cosmos.Sql/FSharp.Azure.Cosmos.Sql.fsproj |
Configures the non-packable library. |
src/Cosmos.Sql/ImmutableArrayPatterns.fs |
Adds length-based active patterns. |
tests/Cosmos.Sql.Tests/EquatableArrayTests.fs |
Tests collections and patterns. |
tests/Cosmos.Sql.Tests/FSharp.Azure.Cosmos.Sql.Tests.fsproj |
Configures the unit-test project. |
tests/Cosmos.Sql.Tests/TestCategories.fs |
Defines the collections test category. |
tests/Cosmos.Sql.Tests/testconfig.json |
Enables parallel test execution. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
xperiandri
added a commit
that referenced
this pull request
Oct 10, 2026
The maintainer's reviews of 2026-10-10 changed several things the record describes, and it now says so where each belongs. The Hedgehog MSTest adapter (#43): the in-repository copy follows the coding guidelines of this repository, while the upstream pull request keeps upstream's style in a copy of its own, so a change of behaviour goes into both; an invocation that MSTest could not run stops the run instead of being shrunk; Odd and Even stay inside their range; DateOnly and TimeOnly get generators, upstream through hedgehogqa/fsharp-hedgehog#488. The open question of the adapter's code style is answered, with formatting and nullness checking still open. Collections (section 4): the shared collection functions of #47 that return voption and struct tuples, tested with properties in #50, and the rule of one module per pipeline of #49. Build (section 5): why FAKE's DotNet.test cannot run the test applications, and fsprojects/FAKE#2903, which adds DotNet.testMTP. The spec model (sections 6 and 16): EquatableArray and the ImmutableArray patterns are #48 and the model itself #42; the validator returns an ImmutableArray of struct errors. Golden baselines (section 13): a literal type provider was evaluated on the question asked in #46 and rejected, with the reasons. Tests (section 22): test category attributes sorted by name, Pascal-case assertion functions and ImmutableArray for shared test data. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
xperiandri
added a commit
that referenced
this pull request
Oct 10, 2026
The maintainer's reviews of 2026-10-10 changed several things the record describes, and it now says so where each belongs. The Hedgehog MSTest adapter (#43): the in-repository copy follows the coding guidelines of this repository, while the upstream pull request keeps upstream's style in a copy of its own, so a change of behaviour goes into both; an invocation that MSTest could not run stops the run instead of being shrunk; the cancellation token is checked after every invocation, whatever its outcome, which the automatic review of #50 asked for; Odd and Even stay inside their range; DateOnly and TimeOnly get generators, upstream through hedgehogqa/fsharp-hedgehog#488. The open question of the adapter's code style is answered, with formatting and nullness checking still open. Collections (section 4): the shared collection functions of #47 that return voption and struct tuples, tested with properties in #50, and the rule of one module per pipeline of #49. Build (section 5): why FAKE's DotNet.test cannot run the test applications, and fsprojects/FAKE#2903, which adds DotNet.testMTP. The spec model (sections 6 and 16): EquatableArray and the ImmutableArray patterns are #48 and the model itself #42; the validator returns an ImmutableArray of struct errors. Golden baselines (section 13): a literal type provider was evaluated on the question asked in #46 and rejected, with the reasons. Tests (section 22): test category attributes sorted by name, Pascal-case assertion functions and ImmutableArray for shared test data. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
xperiandri
force-pushed
the
feat/cosmos-sql-equatable-array
branch
from
October 10, 2026 16:23
8a4d5ff to
a16aa6a
Compare
xperiandri
added a commit
that referenced
this pull request
Oct 10, 2026
The maintainer's reviews of 2026-10-10 changed several things the record describes, and it now says so where each belongs. The Hedgehog MSTest adapter (#43): the in-repository copy follows the coding guidelines of this repository, while the upstream pull request keeps upstream's style in a copy of its own, so a change of behaviour goes into both; an invocation that MSTest could not run stops the run instead of being shrunk; the cancellation token is checked after every invocation, whatever its outcome, which the automatic review of #50 asked for; Odd and Even stay inside their range; DateOnly and TimeOnly get generators, upstream through hedgehogqa/fsharp-hedgehog#488. The open question of the adapter's code style is answered, with formatting and nullness checking still open. Collections (section 4): the shared collection functions of #47 that return voption and struct tuples, tested with properties in #50, and the rule of one module per pipeline of #49. Build (section 5): why FAKE's DotNet.test cannot run the test applications, and fsprojects/FAKE#2903, which adds DotNet.testMTP. The spec model (sections 6 and 16): EquatableArray and the ImmutableArray patterns are #48 and the model itself #42; the validator returns an ImmutableArray of struct errors. Golden baselines (section 13): a literal type provider was evaluated on the question asked in #46 and rejected, with the reasons. Tests (section 22): test category attributes sorted by name, Pascal-case assertion functions and ImmutableArray for shared test data. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 of 6 tasks
xperiandri
added a commit
that referenced
this pull request
Oct 10, 2026
The maintainer's reviews of 2026-10-10 changed several things the record describes, and it now says so where each belongs. The Hedgehog MSTest adapter (#43): the in-repository copy follows the coding guidelines of this repository, while the upstream pull request keeps upstream's style in a copy of its own, so a change of behaviour goes into both; an invocation that MSTest could not run stops the run instead of being shrunk; the cancellation token is checked after every invocation, whatever its outcome, which the automatic review of #50 asked for; Odd and Even stay inside their range; DateOnly and TimeOnly get generators, upstream through hedgehogqa/fsharp-hedgehog#488. The open question of the adapter's code style is answered, formatting and nullness checking included: the two projects are formatted with Fantomas and build with nullness checking on, and only the verbatim port keeps upstream's settings. Collections (section 4): the shared collection functions of #47 that return voption and struct tuples, tested with properties in #50, and the rule of one module per pipeline of #49. Build (section 5): why FAKE's DotNet.test cannot run the test applications, and fsprojects/FAKE#2903, which adds DotNet.testMTP. The spec model (sections 6 and 16): EquatableArray and the ImmutableArray patterns are #48 and the model itself #42; the validator returns an ImmutableArray of struct errors. Golden baselines (section 13): a literal type provider was evaluated on the question asked in #46 and rejected, with the reasons. Tests (section 22): test category attributes sorted by name, in #51 with an instruction scoped to those files, Pascal-case assertion functions and ImmutableArray for shared test data. Two more answers of the same day: the Windows emulator lane of #45 runs weekly instead of nightly (section 2), and the shared collection functions of #47 are in the namespace FSharp.Azure.Cosmos instead of the global one (section 4). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
xperiandri
added a commit
that referenced
this pull request
Oct 10, 2026
The maintainer's reviews of 2026-10-10 changed several things the record describes, and it now says so where each belongs. The Hedgehog MSTest adapter (#43): the in-repository copy follows the coding guidelines of this repository, while the upstream pull request keeps upstream's style in a copy of its own, so a change of behaviour goes into both; an invocation that MSTest could not run stops the run instead of being shrunk; the cancellation token is checked after every invocation, whatever its outcome, which the automatic review of #50 asked for; Odd and Even stay inside their range; DateOnly and TimeOnly get generators, upstream through hedgehogqa/fsharp-hedgehog#488. The open question of the adapter's code style is answered, formatting and nullness checking included: the two projects are formatted with Fantomas and build with nullness checking on, and only the verbatim port keeps upstream's settings. Collections (section 4): the shared collection functions of #47 that return voption and struct tuples, tested with properties in #50, and the rule of one module per pipeline of #49. Build (section 5): why FAKE's DotNet.test cannot run the test applications, and fsprojects/FAKE#2903, which adds DotNet.testMTP. The spec model (sections 6 and 16): EquatableArray and the ImmutableArray patterns are #48 and the model itself #42; the validator returns an ImmutableArray of struct errors. Golden baselines (section 13): a literal type provider was evaluated on the question asked in #46 and rejected, with the reasons. Tests (section 22): test category attributes sorted by name, in #51 with an instruction scoped to those files, Pascal-case assertion functions and ImmutableArray for shared test data. Two more answers of the same day: the Windows emulator lane of #45 runs weekly instead of nightly (section 2), and the shared collection functions of #47 are in the namespace FSharp.Azure.Cosmos instead of the global one (section 4). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
xperiandri
force-pushed
the
feat/cosmos-sql-equatable-array
branch
3 times, most recently
from
October 11, 2026 09:03
fa1d6fb to
fe8b9ef
Compare
xperiandri
added a commit
that referenced
this pull request
Oct 11, 2026
The maintainer's reviews of 2026-10-10 changed several things the record describes, and it now says so where each belongs. The Hedgehog MSTest adapter (#43): the in-repository copy follows the coding guidelines of this repository, while the upstream pull request keeps upstream's style in a copy of its own, so a change of behaviour goes into both; an invocation that MSTest could not run stops the run instead of being shrunk; the cancellation token is checked after every invocation, whatever its outcome, which the automatic review of #50 asked for; Odd and Even stay inside their range; DateOnly and TimeOnly get generators, upstream through hedgehogqa/fsharp-hedgehog#488. The open question of the adapter's code style is answered, formatting and nullness checking included: the two projects are formatted with Fantomas and build with nullness checking on, and only the verbatim port keeps upstream's settings. Collections (section 4): the shared collection functions of #47 that return voption and struct tuples, tested with properties in #50, and the rule of one module per pipeline of #49. Build (section 5): why FAKE's DotNet.test cannot run the test applications, and fsprojects/FAKE#2903, which adds DotNet.testMTP. The spec model (sections 6 and 16): EquatableArray and the ImmutableArray patterns are #48 and the model itself #42; the validator returns an ImmutableArray of struct errors. Golden baselines (section 13): a literal type provider was evaluated on the question asked in #46 and rejected, with the reasons. Tests (section 22): test category attributes sorted by name, in #51 with an instruction scoped to those files, Pascal-case assertion functions and ImmutableArray for shared test data. Two more answers of the same day: the Windows emulator lane of #45 runs weekly instead of nightly (section 2), and the shared collection functions of #47 are in the namespace FSharp.Azure.Cosmos instead of the global one (section 4). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 of 6 tasks
xperiandri
commented
Oct 11, 2026
xperiandri
commented
Oct 11, 2026
xperiandri
force-pushed
the
feat/cosmos-sql-equatable-array
branch
from
October 11, 2026 09:55
fe8b9ef to
1031d6d
Compare
3 of 6 tasks
xperiandri
force-pushed
the
feat/cosmos-sql-equatable-array
branch
from
October 11, 2026 11:03
1031d6d to
7f0a02e
Compare
xperiandri
added a commit
that referenced
this pull request
Oct 11, 2026
The maintainer's reviews of 2026-10-10 changed several things the record describes, and it now says so where each belongs. The Hedgehog MSTest adapter (#43): the in-repository copy follows the coding guidelines of this repository, while the upstream pull request keeps upstream's style in a copy of its own, so a change of behaviour goes into both; an invocation that MSTest could not run stops the run instead of being shrunk; the cancellation token is checked after every invocation, whatever its outcome, which the automatic review of #50 asked for; Odd and Even stay inside their range; DateOnly and TimeOnly get generators, upstream through hedgehogqa/fsharp-hedgehog#488. The open question of the adapter's code style is answered, formatting and nullness checking included: the two projects are formatted with Fantomas and build with nullness checking on, and only the verbatim port keeps upstream's settings. Collections (section 4): the shared collection functions of #47 that return voption and struct tuples, tested with properties in #50, and the rule of one module per pipeline of #49. Build (section 5): why FAKE's DotNet.test cannot run the test applications, and fsprojects/FAKE#2903, which adds DotNet.testMTP. The spec model (sections 6 and 16): EquatableArray and the ImmutableArray patterns are #48 and the model itself #42; the validator returns an ImmutableArray of struct errors. Golden baselines (section 13): a literal type provider was evaluated on the question asked in #46 and rejected, with the reasons. Tests (section 22): test category attributes sorted by name, in #51 with an instruction scoped to those files, Pascal-case assertion functions and ImmutableArray for shared test data. Two more answers of the same day: the Windows emulator lane of #45 runs weekly instead of nightly (section 2), and the shared collection functions of #47 are in the namespace FSharp.Azure.Cosmos instead of the global one (section 4). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
xperiandri
added a commit
that referenced
this pull request
Oct 11, 2026
Section 4 said that an F# record or union holding an ImmutableArray loses structural equality. It does not: the equality the compiler generates goes through IStructuralEquatable, which the array implements, and compares the elements. What is true is narrower. The array's own Equals, which EqualityComparer.Default calls, compares references, so a struct tuple, a HashSet with the default comparer and a C# caller see two equal arrays as different. The structural path boxes every element, hashes only the last eight, throws on compare for different lengths, and a default array never equals an empty one. The section now gives these as the reasons for EquatableArray, as the documentation comment of the type in #48 already does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mutableArray` patterns Starts src/Cosmos.Sql (FSharp.Azure.Cosmos.Sql, net10.0, FSharp.Core only), the project of the Cosmos DB SQL model of ADR 0001 (sections 4, 6 and 15), with the two collection helpers that the syntax tree is built from, so that they can be reviewed on their own before the tree, the printer and the validator follow. EquatableArray<'T> is a struct over ImmutableArray<'T> with sequence equality and a combined hash code. ImmutableArray's own Equals and EqualityComparer<T>.Default compare the reference of the wrapped array, which a struct tuple, a default-comparer HashSet or a C# caller would see, and a default array never equals an empty one. The nodes of the syntax tree will hold their children in this wrapper, so that their equality is structural under every comparer. The EquatableArray module creates and maps the arrays; its unsafeOfArray wraps an array without copying it, as ImmutableCollectionsMarshal.AsImmutableArray does, for a caller that gives the array away. Implicit conversions to and from ImmutableArray wrap and unwrap without copying; F# applies them without a warning at method arguments, and with warning FS3391 elsewhere. The struct partial active patterns Arr0, Arr1, Arr2, Arr3 and ArrN match an ImmutableArray by its length without allocating: each returns a struct value option or a bool, and its payload is a struct tuple. tests/Cosmos.Sql.Tests is the new emulator-free MSTest project, with 15 tests under the category Collections: a file for the struct, one for the module and one for the patterns. Both projects join the solution and the solution filter, and the agent instructions list them. The library is not packed yet (IsPackable is false): a push to main publishes every packable project to GitHub Packages, and the collection types alone are no package. The commit that gives the package its metadata removes the setting. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
xperiandri
force-pushed
the
feat/cosmos-sql-equatable-array
branch
from
October 11, 2026 11:50
7f0a02e to
2cc6691
Compare
This was referenced Oct 11, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Proposed Changes
This is the first part of #42, split off as asked there: the project
FSharp.Azure.Cosmos.Sqlwith nothing but the two collection helpers that the syntax tree of the Cosmos DB SQL model (ADR 0001, #34) is built from, so that they can be reviewed on their own. #42 now builds on this branch and adds the syntax tree, the printer, the function catalog and the validator.EquatableArray<'T>(src/Cosmos.Sql/EquatableArray.fs) is an immutable array whose equality compares the elements.ImmutableArray<'T>cannot hold the children of a syntax node: its ownEqualscompares the reference of the array it wraps. Two separately built nodes with equal children would then be equal only under the comparers that go throughIStructuralEquatable, such as the equality F# generates for records and unions, and unequal inside a struct tuple, in aHashSetwith the default comparer or for a C# caller.EquatableArrayis a struct over anImmutableArraywith element-wise equality and a combined hash code; its default value behaves as an empty array and equals one. TheEquatableArraymodule creates and maps the arrays:empty,ofImmutableArray,ofArray,unsafeOfArray,ofSeq,singleton,toImmutableArray,map.ofArraycopies the array;unsafeOfArraywraps it without a copy, asImmutableCollectionsMarshal.AsImmutableArraydoes, for a caller that gives the array away and never writes to it again. Two implicit conversions (op_Implicit), to and fromImmutableArray<'T>, wrap and unwrap without copying, so either type can be given where the other is expected. F# applies them without a warning only at method arguments; in a union case, a record field, an annotated binding or an argument of a let-bound function it applies them with warning FS3391, so F# code there keeps callingofImmutableArrayandtoImmutableArray. C# applies them everywhere.Arr0,Arr1,Arr2,Arr3,ArrN(src/Cosmos.Sql/ImmutableArrayPatterns.fs) are active patterns that match anImmutableArrayby its length, so that code over the children of a node reads like a list pattern without converting to an F# list. Each one returns a struct value option, or abool, and its payload is a struct tuple, so a match allocates nothing.The rest is the frame for these two files: the library project, the emulator-free MSTest project
tests/Cosmos.Sql.Tests, the entries in the solution and the solution filter, and the solution tree of the agent instructions.The library is not packed yet:
IsPackableisfalse. A push tomainpublishes every packable project to GitHub Packages, and the two collection types alone are no package. #42 removes the setting in the commit that gives the package its metadata.Types of changes
Checklist
Further comments
Collections, no emulator, in a file for the struct (EquatableArrayTests.fs), one for the module (EquatableArrayModuleTests.fs) and one for the patterns (ImmutableArrayPatternsTests.fs): equality and hashing, the default value, equality under the default comparer, in a struct tuple and in aHashSet, the read-only list view, the functions of the module, the implicit conversions (that they do not copy, and that a default array becomes an empty one in both directions),ToString, and the patterns for every length including a default array.FSharp.Azure.Cosmos.Sql, a syntax tree, printer, validator and function catalog for Cosmos DB SQL #42: the two tests that compare whole syntax trees were part ofEquatableArrayTests; they need the tree, so they areSyntaxTeststhere.FSharp.Azure.Cosmos.Sql, a syntax tree, printer, validator and function catalog for Cosmos DB SQL #42 applied here too: a documentation comment without tags is plain///lines, and the test categories are sorted by name.dotnet build FSharp.Azure.Cosmos.slnxin Debug and Release, 15 of 15 tests in both, Fantomas clean, the documentation builds with--strict, anddotnet packproduces no package for the project.Assert.Contains, which asks the set itself and so still goes through the hash code; the tests are split into the three files above;unsafeOfArrayis added, and the tests create their arrays with it, except the test that checks thatofArrayandofSeqcopy.FSharp.Azure.Cosmos.Sql, a syntax tree, printer, validator and function catalog for Cosmos DB SQL #42.🤖 Generated with Claude Code