Skip to content

Commit abd1c71

Browse files
xperiandriclaude
andcommitted
docs: add FlatList.Parallel and the Frozen alternate lookup to ADR 0001
Moves both items from follow-ups into the decision: a nested `FlatList.Parallel` module mirroring `Array.Parallel` through the zero-copy bridge, delivered as its own pull request after `FlatList`, and `alternateLookup`/`tryAlternateLookup` on `FrozenMap`/`FrozenSet` under `#if NET10_0_OR_GREATER`, delivered inside the Frozen pull requests. The appendices gain the matching matrix rows. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
1 parent 420945c commit abd1c71

1 file changed

Lines changed: 36 additions & 5 deletions

File tree

‎docsSrc/Explanations/ADR_0001_Collection_Modules.md‎

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,17 +178,36 @@ functions and that the override functions are equivalent to the defaults after c
178178
### D9. Delivery: one pull request per collection, stacked
179179

180180
`chore/foundation` (helper module, order check script, test categories and contract bases, changelog and documentation
181-
skeleton, target frameworks), then `feat/flat-list`, `feat/indexed-list`, `feat/queue`, `feat/stack`, `feat/hash-map` (with
182-
`IMap`), `feat/sorted-map`, `feat/hash-set` (with `ISet`), `feat/sorted-set`, `feat/frozen-map`, `feat/frozen-set`, and an
183-
optional `chore/benchmarks` (BenchmarkDotNet, excluded from the solution filter). Each pull request deletes the legacy file
181+
skeleton, target frameworks), then `feat/flat-list`, `feat/flat-list-parallel` (the nested `Parallel` module of D11),
182+
`feat/indexed-list`, `feat/queue`, `feat/stack`, `feat/hash-map` (with `IMap`), `feat/sorted-map`, `feat/hash-set` (with
183+
`ISet`), `feat/sorted-set`, `feat/frozen-map`, `feat/frozen-set` (both with the alternate lookup of D11), and an optional
184+
`chore/benchmarks` (BenchmarkDotNet, excluded from the solution filter). Each pull request deletes the legacy file
184185
it replaces, keeps the build green and updates the changelog and the documentation table. No release is cut mid-chain.
185186

186187
### D10. Target frameworks
187188

188189
`net8.0;net10.0`. The published package already targeted `net8.0` only; `netstandard2.0` is not added (the LINQ surface
189190
used in D5 would need conditional fallbacks); `net9.0` is not added (short-term support, ended 2026-05; the `net8.0` asset
190-
serves it). `net10.0` enables `#if NET10_0_OR_GREATER` paths for newer LINQ members and, as a follow-up, the Frozen
191-
alternate lookup.
191+
serves it). `net10.0` enables `#if NET10_0_OR_GREATER` paths for newer LINQ members and the Frozen alternate lookup (D11).
192+
193+
### D11. `FlatList.Parallel` and the Frozen alternate lookup
194+
195+
`FlatList` gets a nested module `Parallel` that mirrors `Array.Parallel` through the zero-copy bridge of D5: every function
196+
unwraps the array, calls `Array.Parallel.*` and wraps the fresh result (`map`, `mapi`, `choose`, `collect`, `filter`, `init`,
197+
`iter`, `iteri`, `zip`, `groupBy`, `partition`, `partitionWith`, `sort`, `sortBy`, `sortByDescending`, `sortDescending`,
198+
`sortWith`, `reduce`, `reduceBy`, `sum`, `sumBy`, `average`, `averageBy`, `max`, `maxBy`, `min`, `minBy`, `exists`, `forall`,
199+
`tryFind`, `tryFindIndex`, `tryPick`); the three `sortInPlace*` functions are omitted because they mutate. The nested module
200+
lives in `FlatList.fsi`/`FlatList.fs` (as `Array.Parallel` lives in `array.fs`) with its own category banners, and has its
201+
`Option` and `Tuple` counterparts (`choose`, `tryFind`, `tryFindIndex`, `tryPick`; `groupBy`, `partition`, `partitionWith`,
202+
`zip`). Its tests compare every function with the sequential `FlatList` counterpart on the same inputs.
203+
204+
`FrozenMap` and `FrozenSet` expose `alternateLookup<'Alternate>` (`GetAlternateLookup`) and `tryAlternateLookup<'Alternate>`
205+
(`TryGetAlternateLookup`, returning `voption`) under `#if NET10_0_OR_GREATER`, because the API exists only in the `net9.0`
206+
and later assets of the package. They return the BCL `AlternateLookup<'Alternate>` struct; callers with a
207+
`ReadOnlySpan<char>` alternate use its `ContainsKey`/`TryGetValue`/`Contains` members directly, since F# cannot instantiate
208+
its own generic functions with byref-like type arguments, so no `findAlternate`-style wrappers are added. The comparer must
209+
implement `IAlternateEqualityComparer<'Alternate, 'Key>` (as `StringComparer.Ordinal` does); `tryAlternateLookup` returns
210+
`ValueNone` otherwise. The tests for these functions compile only for `net10.0`.
192211

193212
## Consequences
194213

@@ -338,6 +357,12 @@ their element-type-changing transformations return the concrete type.
338357
| **Type-specific** | | | | | | | | | |
339358
| `clear` | | – | – | ᵇ | – | ᵇ | – | ᵇ | keeps the implementation |
340359
| `isDefault` / `isDefaultOrEmpty` | | ᵇ | – | – | – | – | – | – | accept a default `FlatList` |
360+
| **Parallel** (nested module `FlatList.Parallel`, mirrors `Array.Parallel`; same category order inside) | | | | | | | | | |
361+
| `average` / `averageBy` / `max` / `maxBy` / `min` / `minBy` / `reduce` / `reduceBy` / `sum` / `sumBy` | | ✓ | – | – | – | – | – | – | Folding |
362+
| `choose` / `collect` / `filter` / `init` / `iter` / `iteri` / `map` / `mapi` / `zip` | Ⓥ (`choose`), Ⓣ (`zip`) | ✓ | – | – | – | – | – | – | Transformation (`init`: Creation) |
363+
| `exists` / `forall` / `tryFind` / `tryFindIndex` / `tryPick` | Ⓥ (`try*`) | ✓ | – | – | – | – | – | – | Search |
364+
| `groupBy` / `partition` / `partitionWith` | Ⓣ | ✓ | – | – | – | – | – | – | Partitioning and grouping |
365+
| `sort` / `sortBy` / `sortByDescending` / `sortDescending` / `sortWith` | | ✓ | – | – | – | – | – | – | Sorting; `sortInPlace*` omitted |
341366

342367
`Option.*`: `choose`, `pick`, `tryExactlyOne`, `tryFind`, `tryFindBack`, `tryFindIndex`, `tryFindIndexBack`, `tryHead`,
343368
`tryItem`, `tryLast`, `tryPick`, `tryTail`, `tryUncons`, `unfold`.
@@ -391,6 +416,9 @@ their element-type-changing transformations return the concrete type.
391416
| `partition` | Ⓣ | ✓ | ✓ | ✓ | ✓ | |
392417
| **Conversion** | | | | | | |
393418
| `toArray` / `toList` / `toSeq` | Ⓣ | ✓ | ✓ | ✓ | ✓ | `struct ('Key * 'Value)` |
419+
| **Type-specific** | | | | | | |
420+
| `alternateLookup<'Alternate>` | | – | – | – | ᵇ | `GetAlternateLookup`; `#if NET10_0_OR_GREATER` |
421+
| `tryAlternateLookup<'Alternate>` | Ⓥ | – | – | – | ᵇ | `TryGetAlternateLookup`; `#if NET10_0_OR_GREATER` |
394422

395423
`Option.*`: `change`, `choose`, `pick`, `tryFind`, `tryFindKey`, `tryGetKey`, `tryPick`. `Tuple.*`: `addRange`, `ofArray`,
396424
`ofList`, `ofSeq`, `ofSeqWithKeyComparer`, `partition`, `toArray`, `toList`, `toSeq` (+ `maxKeyValue`, `minKeyValue` for
@@ -436,5 +464,8 @@ their element-type-changing transformations return the concrete type.
436464
| **Conversion** | | | | | | |
437465
| `toArray` / `toList` / `toSeq` | | ✓ | ✓ | ✓ | ✓ | |
438466
| `toFlatList` | | – | – | – | ᵇ | O(1) via `Items` |
467+
| **Type-specific** | | | | | | |
468+
| `alternateLookup<'Alternate>` | | – | – | – | ᵇ | `GetAlternateLookup`; `#if NET10_0_OR_GREATER` |
469+
| `tryAlternateLookup<'Alternate>` | Ⓥ | – | – | – | ᵇ | `TryGetAlternateLookup`; `#if NET10_0_OR_GREATER` |
439470

440471
`Option.*`: `choose`, `tryGetValue` (+ `tryItem` for `SortedSet`). `Tuple.*`: `partition`, `partitionWith`.

0 commit comments

Comments
 (0)