diff --git a/lib/haskell/map.sx b/lib/haskell/map.sx index 96fb6dfb..6d30a316 100644 --- a/lib/haskell/map.sx +++ b/lib/haskell/map.sx @@ -369,3 +369,53 @@ (cond ((hk-map-member k m2) acc) (:else (hk-map-insert k v acc))))) hk-map-empty (hk-map-to-asc-list m1)))) + +(define + hk-map-foldl-with-key + (fn + (f acc m) + (cond + ((hk-map-empty? m) acc) + (:else + (let + ((acc1 (hk-map-foldl-with-key f acc (hk-map-left m)))) + (let + ((acc2 (f acc1 (hk-map-key m) (hk-map-val m)))) + (hk-map-foldl-with-key f acc2 (hk-map-right m)))))))) + +(define + hk-map-foldr-with-key + (fn + (f acc m) + (cond + ((hk-map-empty? m) acc) + (:else + (let + ((acc1 (hk-map-foldr-with-key f acc (hk-map-right m)))) + (let + ((acc2 (f (hk-map-key m) (hk-map-val m) acc1))) + (hk-map-foldr-with-key f acc2 (hk-map-left m)))))))) + +(define + hk-map-map-with-key + (fn + (f m) + (cond + ((hk-map-empty? m) m) + (:else + (list + "Map-Node" + (hk-map-key m) + (f (hk-map-key m) (hk-map-val m)) + (hk-map-map-with-key f (hk-map-left m)) + (hk-map-map-with-key f (hk-map-right m)) + (hk-map-size m)))))) + +(define + hk-map-filter-with-key + (fn + (p m) + (hk-map-foldr-with-key + (fn (k v acc) (cond ((p k v) (hk-map-insert k v acc)) (:else acc))) + hk-map-empty + m))) diff --git a/plans/haskell-completeness.md b/plans/haskell-completeness.md index 658d5abd..45385681 100644 --- a/plans/haskell-completeness.md +++ b/plans/haskell-completeness.md @@ -186,7 +186,7 @@ No OCaml changes are needed. The view type is fully representable as an SX dict. `member`, `size`, `null`. - [x] Bulk operations: `fromList`, `toList`, `toAscList`, `keys`, `elems`. - [x] Combining: `unionWith`, `intersectionWith`, `difference`. -- [ ] Transforming: `foldlWithKey`, `foldrWithKey`, `mapWithKey`, `filterWithKey`. +- [x] Transforming: `foldlWithKey`, `foldrWithKey`, `mapWithKey`, `filterWithKey`. - [ ] Updating: `adjust`, `insertWith`, `insertWithKey`, `alter`. - [ ] Module wiring: `import Data.Map` and `import qualified Data.Map as Map` resolve to the `map.sx` namespace dict in the eval import handler. @@ -304,6 +304,16 @@ No OCaml changes are needed. The view type is fully representable as an SX dict. _Newest first._ +**2026-05-07** — Phase 11 transforming (foldlWithKey/foldrWithKey/mapWithKey/filterWithKey): +- Folds traverse in-order. `foldlWithKey f acc m` walks left → key/val → right + threading the accumulator, so left-folding `(\acc k v -> acc ++ k ++ v)` over + a 3-key map yields `"1a2b3c"`. `foldrWithKey` runs right → key/val → left so + the cons-style accumulator `(\k v acc -> k ++ v ++ acc)` produces the same + string. +- `mapWithKey` rebuilds the tree node-by-node (no rebalancing needed — keys + unchanged so the existing structure stays valid). `filterWithKey` is a + `foldrWithKey` that re-inserts kept entries; rebalances via insert. + **2026-05-07** — Phase 11 combining (unionWith/intersectionWith/difference): - All three implemented via `reduce` over the smaller map's `to-asc-list`, inserting / skipping into the result. Verified: