@@ -50,11 +50,13 @@ 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 `
59+ ` cons ` /` uncons ` /` tryUncons ` , the struct partial patterns ` (|Cons|_|) ` / ` (| Nil|_ |)` , ` tryTail ` , ` enqueue ` /` enqueueMany ` , ` consMany ` , ` takeLast ` /` skipLast ` , ` clear `
5860on interface modules, ` tryGetKey ` /` tryGetValue ` , ` setItem ` /` setItems ` /` addRange ` /` removeRange ` , ` containsValue ` ,
5961` symmetricDifference ` , ` overlaps ` /` setEquals ` , comparer accessors and ` with*Comparer ` functions.
6062
@@ -76,7 +78,7 @@ Names: `IMap` module and `IMap<'Key, 'Value>` abbreviation for `IImmutableDictio
7678Maps and sets measure their size with ` count ` (FSharp.Core ` Map.count ` /` Set.count ` ), sequences with ` length ` . ` Queue ` keeps
7779` enqueue ` /` head ` /` tail ` /` uncons ` (compiled ` Enqueue ` /` Peek ` /` Dequeue ` /` PeekDequeue ` ), ` Stack ` keeps ` cons ` /` head ` /` tail ` /
7880` uncons ` (` Push ` /` Peek ` /` Pop ` /` PeekPop ` ). Computation expression instances: ` flatList ` , ` indexedList ` , ` queue ` , ` stack ` ,
79- ` hashMap ` , ` sortedMap ` , ` hashSet ` , ` sortedSet ` , ` frozenMap ` , ` frozenSet ` .
81+ ` hashMap ` , ` sortedMap ` , ` hashSet ` , ` sortedSet ` , ` frozenMap ` , ` frozenSet ` , and ` equatableArray ` of ADR 0002 .
8082
8183### D3. Value-type defaults and the ` Option ` /` Tuple ` override namespaces
8284
@@ -147,8 +149,9 @@ FSharp.Core module that a collection mirrors: `FlatList` and `FlatList.Parallel`
147149` Array.Parallel.sort* ` are documented ("This is not a stable sort"), through ` ImmutableArray.Sort ` or ` Array.sort* ` on the
148150bridge; ` IndexedList ` , ` Queue ` , ` Stack ` and their interface modules sort stably, as ` List.sort* ` and ` Seq.sort* ` are
149151documented, 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.
152+ Every sort compares in the order of F# generic comparison (` LanguagePrimitives.FastGenericComparer<'T> ` , the comparer
153+ behind ` compare ` ), never with a culture-sensitive comparer such as ` Comparer<string>.Default ` . ADR 0002 §3 shows the
154+ effect on strings and uses the same order for the elements of ` EquatableArray ` .
152155
153156Consequences for the types: ` FlatList ` range operations (` take ` , ` skip ` , ` truncate ` , ` splitAt ` , ` takeLast ` , ` skipLast ` ,
154157` chunkBySize ` , ` windowed ` ) copy the selected elements. An ` ImmutableArray ` is a single array reference without an offset or a
@@ -190,18 +193,21 @@ which sorts unstably, see D5); `Map`, `MapTransform`, `MapMutation`, `MapCreatio
190193observed enumeration order, so one test body serves FIFO, LIFO and indexed collections. Collection-specific behaviour
191194(` isDefault ` , spans, builders, ` Stack.cons ` direction, comparers, sorted-only functions, null inputs) lives in a per-collection
192195file. Exceptions are asserted with ` Assert.ThrowsExactly ` on type, ` ParamName ` and message prefix; every assertion carries
193- a message; categories come from ` TestCategories.fs ` attributes (collection level) and ` TestCategory ` strings or ` nameof `
194- (operation level). Dedicated files per collection prove that opening the ` Option ` /` Tuple ` namespaces shadows the default
196+ a message; categories come from ` TestCategories.fs ` attributes (collection level) and ` TestCategory (nameof …) `
197+ (operation level), never from string literals. In a contract base, the function of any module gives the name, for
198+ example ` nameof FlatList.map ` . Dedicated files per collection prove that opening the ` Option ` /` Tuple ` namespaces shadows the default
195199functions and that the override functions are equivalent to the defaults after conversion.
196200
197201### D9. Delivery: one pull request per collection, stacked
198202
199203` chore/foundation ` (helper module, order check script, test categories and contract bases, changelog and documentation
200204skeleton, target frameworks), then ` feat/flat-list ` , ` feat/flat-list-parallel ` (the nested ` Parallel ` module of D11),
201- ` feat/indexed-list ` , ` feat/queue ` , ` feat/stack ` , ` feat/hash-map ` (with ` IMap ` ), ` feat/sorted-map ` , ` feat/hash-set ` (with
205+ ` feat/equatable-array ` (step 2 of ADR 0002: the mirror of the ` FlatList ` module, its builder functions and
206+ ` equatableArray { } ` ), ` feat/indexed-list ` , ` feat/queue ` , ` feat/stack ` , ` feat/hash-map ` (with ` IMap ` ), ` feat/sorted-map ` , ` feat/hash-set ` (with
202207` ISet ` ), ` feat/sorted-set ` , ` feat/frozen-map ` , ` feat/frozen-set ` (both with the alternate lookup of D11), and an optional
203208` chore/benchmarks ` (BenchmarkDotNet, excluded from the solution filter). Each pull request deletes the legacy file
204209it replaces, keeps the build green and updates the changelog and the documentation table. No release is cut mid-chain.
210+ Step 1 of ADR 0002 (the ` EquatableArray ` type, its patterns and JSON converter) MAY ship from ` main ` before the chain.
205211
206212### D10. Target frameworks
207213
@@ -317,7 +323,8 @@ their element-type-changing transformations return the concrete type.
317323| ` tryTail ` | Ⓥ | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | |
318324| ` tryUncons ` | Ⓥ+Ⓣ | – | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | ` struct ('T * X<'T>) voption ` |
319325| ` uncons ` | Ⓣ | – | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | compiled ` PeekDequeue ` /` PeekPop ` |
320- | ` (\|Cons\|Nil\|) ` | Ⓣ | – | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | |
326+ | ` (\|Cons\|_\|) ` | Ⓥ+Ⓣ | – | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | ` [<return: Struct>] ` , ` struct ('T * X<'T>) voption ` ; a multi-case pattern allocates a ` Choice ` per match (ADR 0002 §5) |
327+ | ` (\|Nil\|_\|) ` | | – | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | ᵃ | returns ` bool ` |
321328| ** Search** | | | | | | | | | |
322329| ` binarySearch ` | | ᵇ | ᵇ | – | – | – | – | – | BCL bitwise-complement contract |
323330| ` contains ` | | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | |
@@ -395,9 +402,12 @@ their element-type-changing transformations return the concrete type.
395402| ` sort ` / ` sortBy ` / ` sortByDescending ` / ` sortDescending ` / ` sortWith ` | | ✓ | – | – | – | – | – | – | Sorting, unstable like ` Array.Parallel.sort* ` ; ` sortInPlace* ` omitted |
396403
397404` Option.* ` : ` choose ` , ` pick ` , ` tryExactlyOne ` , ` tryFind ` , ` tryFindBack ` , ` tryFindIndex ` , ` tryFindIndexBack ` , ` tryHead ` ,
398- ` tryItem ` , ` tryLast ` , ` tryPick ` , ` tryTail ` , ` tryUncons ` , ` unfold ` .
405+ ` tryItem ` , ` tryLast ` , ` tryPick ` , ` tryTail ` , ` tryUncons ` , ` unfold ` , ` (|Cons|_|) ` .
399406` Tuple.* ` : ` allPairs ` , ` countBy ` , ` groupBy ` , ` indexed ` , ` mapFold ` , ` mapFoldBack ` , ` pairwise ` , ` partition ` , ` partitionWith ` ,
400- ` splitAt ` , ` unfold ` , ` unzip ` , ` unzip3 ` , ` zip ` , ` zip3 ` , ` uncons ` , ` tryUncons ` , ` (|Cons|Nil|) ` where present.
407+ ` splitAt ` , ` unfold ` , ` unzip ` , ` unzip3 ` , ` zip ` , ` zip3 ` , ` uncons ` , ` tryUncons ` , ` (|Cons|_|) ` where present.
408+
409+ ` EquatableArray<'T> ` of ADR 0002 mirrors the ` FlatList ` column, without ` isDefault ` and ` isDefaultOrEmpty ` , and adds
410+ ` ofImmutableArray ` , ` toImmutableArray ` and ` unsafeOfArray ` .
401411
402412## Appendix B – maps
403413
0 commit comments