fsharp-performance-types
Installation
SKILL.md
F# performance types
Agents write F# collection code that makes several passes, allocates on each element, or uses a tree where a hash table fits. The compiler accepts this code. Human reviewers then ask for changes. Review evidence ranks collection efficiency among the strongest categories of human comments on agent F# code.
For readable shape (records, match, no let mutable accumulators), use fsharp-idiom-review. This skill does not repeat it.
Use this skill only for code that a measurement shows to be hot, or that a reviewer or task names as hot. Outside a hot path, prefer the readable form.
Rules
Collections. references/COLLECTIONS.md has the choice table and examples.
- Iterate an F#
listwithfor,List.fold, or pattern matching. Do not index it, and do not copy it to an array only to loop over it. - Do not enumerate a
seqmore than once. Each enumeration runs the source again. Materialize it once, or compute all results in one pass. - Do not use
@orList.appendin a loop. Cons onto the head and callList.revonce, or fill aResizeArray. - In a hot loop that updates a table, use a local
DictionaryorHashSet.Map.addallocates a new tree path on each update, andMap.tryFindallocates aSomeon each hit. Return an immutable result at the end if the contract requires one. ADictionaryuses .NET equality: passHashIdentity.Structuralwhen the key needs F# structural equality, for example an array key. - Keep the order that the contract defines.
List.sort,Array.sort,Map, andSetorder strings by ordinal.Array.Sort,List<T>.Sort, andSortedDictionaryuse the current culture unless you passStringComparer.Ordinal. - For a lookup table that is built once and read many times, use
FrozenDictionaryorFrozenSet.