From 95cf653ba98ee6c2ebdc1ff50302f0d6e4491a97 Mon Sep 17 00:00:00 2001 From: giles Date: Thu, 7 May 2026 10:00:45 +0000 Subject: [PATCH] =?UTF-8?q?haskell:=20Phase=2011=20=E2=80=94=20Data.Map=20?= =?UTF-8?q?combining=20(unionWith/intersectionWith/difference)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- lib/haskell/map.sx | 49 +++++++++++++++++++++++++++++++++++ plans/haskell-completeness.md | 9 ++++++- 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/lib/haskell/map.sx b/lib/haskell/map.sx index da9671d8..96fb6dfb 100644 --- a/lib/haskell/map.sx +++ b/lib/haskell/map.sx @@ -320,3 +320,52 @@ (append (hk-map-elems (hk-map-left m)) (cons (hk-map-val m) (hk-map-elems (hk-map-right m)))))))) + +(define + hk-map-union-with + (fn + (f m1 m2) + (reduce + (fn + (acc p) + (let + ((k (first p)) (v (nth p 1))) + (let + ((look (hk-map-lookup k acc))) + (cond + ((= (first look) "Just") + (hk-map-insert k (f (nth look 1) v) acc)) + (:else (hk-map-insert k v acc)))))) + m1 + (hk-map-to-asc-list m2)))) + +(define + hk-map-intersection-with + (fn + (f m1 m2) + (reduce + (fn + (acc p) + (let + ((k (first p)) (v1 (nth p 1))) + (let + ((look (hk-map-lookup k m2))) + (cond + ((= (first look) "Just") + (hk-map-insert k (f v1 (nth look 1)) acc)) + (:else acc))))) + hk-map-empty + (hk-map-to-asc-list m1)))) + +(define + hk-map-difference + (fn + (m1 m2) + (reduce + (fn + (acc p) + (let + ((k (first p)) (v (nth p 1))) + (cond ((hk-map-member k m2) acc) (:else (hk-map-insert k v acc))))) + hk-map-empty + (hk-map-to-asc-list m1)))) diff --git a/plans/haskell-completeness.md b/plans/haskell-completeness.md index c06cded0..658d5abd 100644 --- a/plans/haskell-completeness.md +++ b/plans/haskell-completeness.md @@ -185,7 +185,7 @@ No OCaml changes are needed. The view type is fully representable as an SX dict. - [x] Core operations: `empty`, `singleton`, `insert`, `lookup`, `delete`, `member`, `size`, `null`. - [x] Bulk operations: `fromList`, `toList`, `toAscList`, `keys`, `elems`. -- [ ] Combining: `unionWith`, `intersectionWith`, `difference`. +- [x] Combining: `unionWith`, `intersectionWith`, `difference`. - [ ] Transforming: `foldlWithKey`, `foldrWithKey`, `mapWithKey`, `filterWithKey`. - [ ] Updating: `adjust`, `insertWith`, `insertWithKey`, `alter`. - [ ] Module wiring: `import Data.Map` and `import qualified Data.Map as Map` @@ -304,6 +304,13 @@ No OCaml changes are needed. The view type is fully representable as an SX dict. _Newest first._ +**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: + union with `(str a "+" b)` produces `b+B` for the shared key; intersection + with `(+)` over `[1→10,2→20] ⊓ [2→200,3→30]` yields `(2 220)`; difference + preserves `m1` keys absent from `m2`. + **2026-05-07** — Phase 11 bulk operations (fromList/toList/toAscList/keys/elems): - `hk-map-from-list` uses SX `reduce` — left-to-right, so duplicates resolve with last-wins (matches GHC `fromList`). `to-asc-list` is in-order recursive