Skip to content

Extend performance group with strict IORef/State/container folds#1691

Open
mgajda wants to merge 3 commits intondmitchell:masterfrom
mgajda:performance-refs-folds
Open

Extend performance group with strict IORef/State/container folds#1691
mgajda wants to merge 3 commits intondmitchell:masterfrom
mgajda:performance-refs-folds

Conversation

@mgajda
Copy link
Copy Markdown

@mgajda mgajda commented Apr 20, 2026

Layered on top of #1691 (performance-strictness). Merge that one first —
this PR's diff will collapse to its own commit once it lands.

Adds strict-variant rewrites for the remaining high-value targets in
the opt-in performance group. All matches use fully-qualified module
names so they fire only on the specific lazy variants users imported
(no risk of hitting polymorphic/Foldable instances).

Rules added

  • Data.IORef.modifyIORef / atomicModifyIORef → primed forms
  • Control.Monad.State.modifymodify'
  • Data.{Map.Strict, Map.Lazy, Set, IntMap.Strict, IntMap.Lazy, HashMap.Strict, HashMap.Lazy}.foldlfoldl'

Tests

  • cabal build
  • hlint --test — 966 tests pass
  • Manual verification: each rule fires on its exact qualified form only

mgajda added 3 commits April 20, 2026 09:35
New group (enabled: false) flags single-primitive uses of STM where a
non-transactional primitive from IORef/MVar/Chan/QSem gives the same
operation at a fraction of the cost: the transaction log, commit-time
validation, and retry machinery are pure overhead when a transaction
touches a single variable and needs no composition.

Hints cover TVar, TMVar, TChan, TQueue, and TSem. Multi-variable
transactions correctly do not match (no false positives on genuinely
composable STM).

Activate with `--with-group=performance`.
Three additional opt-in hints:

- Data.List.foldl f z x -> Data.List.foldl' f z x
- Data.List.scanl f z x -> Data.List.scanl' f z x
- Data.Set.fromList (map f (Data.Set.toList s)) -> Data.Set.map f s

Only the list-qualified forms of foldl/scanl are matched. Unqualified
`foldl` in Prelude is Data.Foldable.foldl (Foldable-polymorphic), where
the Data.List.foldl' rewrite would be ill-typed on non-list containers.
The same safety is applied to scanl against future generalisations.

Activated together with the STM hints via `--with-group=performance`.
Adds strict-variant rewrites for the remaining high-value targets in the
opt-in performance group. All matches use fully-qualified module names
so they only fire on the specific lazy variants users actually imported.

- Data.IORef.modifyIORef / atomicModifyIORef -> primed forms
- Control.Monad.State.modify -> modify'
- Data.{Map.Strict, Map.Lazy, Set, IntMap.Strict, IntMap.Lazy,
  HashMap.Strict, HashMap.Lazy}.foldl -> foldl'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant