@@ -50,13 +50,16 @@ New collections: `FrozenMap` (`FrozenDictionary<'Key, 'Value>`) and `FrozenSet`
5050creation, lookup, iteration, folds, conversions ** and** whole-collection transformations (` map ` , ` filter ` , ` choose ` ,
5151` partition ` , set algebra), each documented as an O(n) rebuild. They offer no incremental mutation (` add ` , ` remove ` ,
5252` setItem ` , ` change ` , ` clear ` , ` addRange ` , ` removeRange ` ): a frozen collection is built once and read many times.
53+ ADR 0002 – EquatableArray (` ADR_0002_EquatableArray.md ` ) adds ` EquatableArray<'T> ` , an immutable array with value
54+ semantics, whose module mirrors ` FlatList ` .
5355
5456Curated extras kept beyond FSharp.Core: ` indexOf ` /` indexOfWith ` /` lastIndexOf ` /` lastIndexOfWith ` , ` binarySearch ` ,
5557` sortWithComparer ` , ` isDefault ` /` isDefaultOrEmpty ` , ` asSpan ` /` asMemory ` /` ofSpan ` /` ofReadOnlySpan ` , the builder family
5658(` builder ` , ` builderWith ` , ` ofBuilder ` , ` toBuilder ` , ` moveFromBuilder ` , ` build ` , ` update ` ), ` blit ` , ` add ` ,
57- ` cons ` /` uncons ` /` tryUncons ` /` (|Cons|Nil|) ` , ` tryTail ` , ` enqueue ` /` enqueueMany ` , ` consMany ` , ` takeLast ` /` skipLast ` , ` clear `
58- on interface modules, ` tryGetKey ` /` tryGetValue ` , ` setItem ` /` setItems ` /` addRange ` /` removeRange ` , ` containsValue ` ,
59- ` symmetricDifference ` , ` overlaps ` /` setEquals ` , comparer accessors and ` with*Comparer ` functions.
59+ ` cons ` /` uncons ` /` tryUncons ` , the struct partial patterns ` (|Cons|_|) ` /` (|Nil|_|) ` , ` tryTail ` , ` enqueue ` /` enqueueMany ` ,
60+ ` consMany ` , ` takeLast ` /` skipLast ` , ` clear ` on interface modules, ` tryGetKey ` /` tryGetValue ` ,
61+ ` setItem ` /` setItems ` /` addRange ` /` removeRange ` , ` containsValue ` , ` symmetricDifference ` , ` overlaps ` /` setEquals ` , comparer
62+ accessors and ` with*Comparer ` functions.
6063
6164Removed from the started branch: ` iter3 ` /` iteri3 ` /` exists3 ` /` forall3 ` /` mapi3 ` /` foldBack3 ` , ` foldi ` /` foldi2 ` /` foldBacki ` /
6265` foldBacki2 ` , ` findDup ` /` findDupBy ` , ` pickBack ` /` tryPickBack ` /` chooseBack ` , the ` From ` /` Range ` variants of ` index* ` /
@@ -76,7 +79,7 @@ Names: `IMap` module and `IMap<'Key, 'Value>` abbreviation for `IImmutableDictio
7679Maps and sets measure their size with ` count ` (FSharp.Core ` Map.count ` /` Set.count ` ), sequences with ` length ` . ` Queue ` keeps
7780` enqueue ` /` head ` /` tail ` /` uncons ` (compiled ` Enqueue ` /` Peek ` /` Dequeue ` /` PeekDequeue ` ), ` Stack ` keeps ` cons ` /` head ` /` tail ` /
7881` uncons ` (` Push ` /` Peek ` /` Pop ` /` PeekPop ` ). Computation expression instances: ` flatList ` , ` indexedList ` , ` queue ` , ` stack ` ,
79- ` hashMap ` , ` sortedMap ` , ` hashSet ` , ` sortedSet ` , ` frozenMap ` , ` frozenSet ` .
82+ ` hashMap ` , ` sortedMap ` , ` hashSet ` , ` sortedSet ` , ` frozenMap ` , ` frozenSet ` , and ` equatableArray ` of ADR 0002 .
8083
8184### D3. Value-type defaults and the ` Option ` /` Tuple ` override namespaces
8285
@@ -147,8 +150,9 @@ FSharp.Core module that a collection mirrors: `FlatList` and `FlatList.Parallel`
147150` Array.Parallel.sort* ` are documented ("This is not a stable sort"), through ` ImmutableArray.Sort ` or ` Array.sort* ` on the
148151bridge; ` IndexedList ` , ` Queue ` , ` Stack ` and their interface modules sort stably, as ` List.sort* ` and ` Seq.sort* ` are
149152documented, through LINQ ` OrderBy ` /` OrderByDescending ` (documented stable), not through the unstable ` ImmutableList.Sort ` .
150- Every sort compares with F# structural comparison (` LanguagePrimitives.FastGenericComparer<'T> ` , the comparer behind
151- ` compare ` ), never with ` Comparer<'T>.Default ` , which compares strings culture-sensitively.
153+ Every sort compares in the order of F# generic comparison (` LanguagePrimitives.FastGenericComparer<'T> ` , the comparer
154+ behind ` compare ` ), never with a culture-sensitive comparer such as ` Comparer<string>.Default ` . ADR 0002 §3 shows the
155+ effect on strings and uses the same order for the elements of ` EquatableArray ` .
152156
153157Consequences for the types: ` FlatList ` range operations (` take ` , ` skip ` , ` truncate ` , ` splitAt ` , ` takeLast ` , ` skipLast ` ,
154158` chunkBySize ` , ` windowed ` ) copy the selected elements. An ` ImmutableArray ` is a single array reference without an offset or a
@@ -168,7 +172,7 @@ and the element comparer of a set are kept by `filter`, `partition` and set alge
168172element type, so their result gets the default comparer of the new type. The interface modules cannot read the comparers
169173of their input, so their type-changing transformations return concrete collections with default comparers. The defaults,
170174which creation functions without a comparer argument also use, are ` EqualityComparer<'T>.Default ` for hash-based
171- collections and the order of F# generic comparison
175+ collections, as ADR 0002 uses for equality, and the order of F# generic comparison
172176(` LanguagePrimitives.FastGenericComparer<'T> ` ) for sorted collections. Thus ` SortedSet<string> ` is ordinal by default, as
173177F# ` Set<string> ` is.
174178
@@ -223,18 +227,21 @@ observed enumeration order, so one test body serves FIFO, LIFO and indexed colle
223227file. Expected exceptions come from the same oracle: the test calls the function of the mirrored FSharp.Core module (D6)
224228on the same input and asserts the same type and message with ` Assert.ThrowsExactly ` ; ` ParamName ` is checked against the
225229ops record. Every assertion carries a message; categories come from ` TestCategories.fs ` attributes (collection level) and
226- ` TestCategory ` strings or ` nameof ` (operation level). Dedicated files per collection prove that opening the
227- ` Option ` / ` Tuple ` namespaces shadows the default functions and that the override functions are equivalent to the defaults
228- after conversion.
230+ ` TestCategory (nameof …) ` (operation level), never from string literals. In a contract base, the function of any module
231+ gives the name, for example ` nameof FlatList.map ` . Dedicated files per collection prove that opening the ` Option ` / ` Tuple `
232+ namespaces shadows the default functions and that the override functions are equivalent to the defaults after conversion.
229233
230234### D9. Delivery: one pull request per collection, stacked
231235
232236` chore/foundation ` (helper module, order check script, test categories and contract bases, changelog and documentation
233237skeleton, target frameworks), then ` feat/flat-list ` , ` feat/flat-list-parallel ` (the nested ` Parallel ` module of D11),
234- ` feat/indexed-list ` , ` feat/queue ` , ` feat/stack ` , ` feat/hash-map ` (with ` IMap ` ), ` feat/sorted-map ` , ` feat/hash-set ` (with
235- ` ISet ` ), ` feat/sorted-set ` , ` feat/frozen-map ` , ` feat/frozen-set ` (both with the alternate lookup of D11), and an optional
236- ` chore/benchmarks ` (BenchmarkDotNet, excluded from the solution filter). Each pull request deletes the legacy file
237- it replaces, keeps the build green and updates the changelog and the documentation table. No release is cut mid-chain.
238+ ` feat/equatable-array ` (step 2 of ADR 0002: the mirror of the ` FlatList ` module, its builder functions and
239+ ` equatableArray { } ` ), ` feat/indexed-list ` , ` feat/queue ` , ` feat/stack ` , ` feat/hash-map ` (with ` IMap ` ), ` feat/sorted-map ` ,
240+ ` feat/hash-set ` (with ` ISet ` ), ` feat/sorted-set ` , ` feat/frozen-map ` , ` feat/frozen-set ` (both with the alternate lookup of
241+ D11), and an optional ` chore/benchmarks ` (BenchmarkDotNet, excluded from the solution filter). Each pull request deletes
242+ the legacy file it replaces, keeps the build green and updates the changelog and the documentation table. No release is
243+ cut mid-chain.
244+ Step 1 of ADR 0002 (the ` EquatableArray ` type, its patterns and JSON converter) MAY ship from ` main ` before the chain.
238245
239246### D10. Target frameworks
240247
@@ -351,7 +358,8 @@ their element-type-changing transformations return the concrete type.
351358| ` tryTail ` | Ⓥ | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | |
352359| ` tryUncons ` | Ⓥ+Ⓣ | – | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | ` struct ('T * X<'T>) voption ` |
353360| ` uncons ` | Ⓣ | – | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | compiled ` PeekDequeue ` /` PeekPop ` |
354- | ` (\|Cons\|Nil\|) ` | Ⓣ | – | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | |
361+ | ` (\|Cons\|_\|) ` | Ⓥ+Ⓣ | – | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | ` [<return: Struct>] ` , ` struct ('T * X<'T>) voption ` ; a multi-case pattern allocates a ` Choice ` per match (ADR 0002 §5) |
362+ | ` (\|Nil\|_\|) ` | | – | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | returns ` bool ` |
355363| ** Search** | | | | | | | | | |
356364| ` binarySearch ` | | ᵇ | ᵇ | – | – | – | – | – | BCL bitwise-complement contract |
357365| ` contains ` | | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | |
@@ -429,9 +437,12 @@ their element-type-changing transformations return the concrete type.
429437| ` sort ` / ` sortBy ` / ` sortByDescending ` / ` sortDescending ` / ` sortWith ` | | ✓ | – | – | – | – | – | – | Sorting, unstable like ` Array.Parallel.sort* ` ; ` sortInPlace* ` omitted |
430438
431439` Option.* ` : ` choose ` , ` pick ` , ` tryExactlyOne ` , ` tryFind ` , ` tryFindBack ` , ` tryFindIndex ` , ` tryFindIndexBack ` , ` tryHead ` ,
432- ` tryItem ` , ` tryLast ` , ` tryPick ` , ` tryTail ` , ` tryUncons ` , ` unfold ` .
440+ ` tryItem ` , ` tryLast ` , ` tryPick ` , ` tryTail ` , ` tryUncons ` , ` unfold ` , ` (|Cons|_|) ` .
433441` Tuple.* ` : ` allPairs ` , ` countBy ` , ` groupBy ` , ` indexed ` , ` mapFold ` , ` mapFoldBack ` , ` pairwise ` , ` partition ` , ` partitionWith ` ,
434- ` splitAt ` , ` unfold ` , ` unzip ` , ` unzip3 ` , ` zip ` , ` zip3 ` , ` uncons ` , ` tryUncons ` , ` (|Cons|Nil|) ` where present.
442+ ` splitAt ` , ` unfold ` , ` unzip ` , ` unzip3 ` , ` zip ` , ` zip3 ` , ` uncons ` , ` tryUncons ` , ` (|Cons|_|) ` where present.
443+
444+ ` EquatableArray<'T> ` of ADR 0002 mirrors the ` FlatList ` column, without ` isDefault ` and ` isDefaultOrEmpty ` , and adds
445+ ` ofImmutableArray ` , ` toImmutableArray ` and ` unsafeOfArray ` .
435446
436447## Appendix B – maps
437448
0 commit comments