diff --git a/lib/haskell/conformance.sh b/lib/haskell/conformance.sh index 0c34a35c..4c64ea32 100755 --- a/lib/haskell/conformance.sh +++ b/lib/haskell/conformance.sh @@ -39,6 +39,7 @@ run_suite() { (load "lib/haskell/match.sx") (load "lib/haskell/eval.sx") (load "lib/haskell/map.sx") +(load "lib/haskell/set.sx") (load "lib/haskell/testlib.sx") (epoch 2) (load "$FILE") diff --git a/lib/haskell/eval.sx b/lib/haskell/eval.sx index bcf9087f..1692cc20 100644 --- a/lib/haskell/eval.sx +++ b/lib/haskell/eval.sx @@ -1123,6 +1123,89 @@ (:else (hk-force d))))) 3)))))) +(define + hk-bind-data-set! + (fn + (env alias) + (let + ((p (str alias "."))) + (begin + (dict-set! env (str p "empty") hk-set-empty) + (dict-set! + env + (str p "singleton") + (hk-mk-lazy-builtin + "Set.singleton" + (fn (k) (hk-set-singleton (hk-force k))) + 1)) + (dict-set! + env + (str p "insert") + (hk-mk-lazy-builtin + "Set.insert" + (fn (k s) (hk-set-insert (hk-force k) (hk-force s))) + 2)) + (dict-set! + env + (str p "delete") + (hk-mk-lazy-builtin + "Set.delete" + (fn (k s) (hk-set-delete (hk-force k) (hk-force s))) + 2)) + (dict-set! + env + (str p "member") + (hk-mk-lazy-builtin + "Set.member" + (fn + (k s) + (hk-of-bool (hk-set-member (hk-force k) (hk-force s)))) + 2)) + (dict-set! + env + (str p "size") + (hk-mk-lazy-builtin + "Set.size" + (fn (s) (hk-set-size (hk-force s))) + 1)) + (dict-set! + env + (str p "null") + (hk-mk-lazy-builtin + "Set.null" + (fn (s) (hk-of-bool (hk-set-null (hk-force s)))) + 1)) + (dict-set! + env + (str p "union") + (hk-mk-lazy-builtin + "Set.union" + (fn (a b) (hk-set-union (hk-force a) (hk-force b))) + 2)) + (dict-set! + env + (str p "intersection") + (hk-mk-lazy-builtin + "Set.intersection" + (fn (a b) (hk-set-intersection (hk-force a) (hk-force b))) + 2)) + (dict-set! + env + (str p "difference") + (hk-mk-lazy-builtin + "Set.difference" + (fn (a b) (hk-set-difference (hk-force a) (hk-force b))) + 2)) + (dict-set! + env + (str p "isSubsetOf") + (hk-mk-lazy-builtin + "Set.isSubsetOf" + (fn + (a b) + (hk-of-bool (hk-set-is-subset-of (hk-force a) (hk-force b)))) + 2)))))) + (define hk-bind-decls! (fn @@ -1280,9 +1363,15 @@ (let ((modname (nth d 2)) (as-name (nth d 3))) (let - ((alias (cond ((nil? as-name) "Map") (:else as-name)))) + ((alias + (cond + ((not (nil? as-name)) as-name) + ((= modname "Data.Map") "Map") + ((= modname "Data.Set") "Set") + (:else modname)))) (cond ((= modname "Data.Map") (hk-bind-data-map! env alias)) + ((= modname "Data.Set") (hk-bind-data-set! env alias)) (:else nil))))) (:else nil))) decls) diff --git a/lib/haskell/test.sh b/lib/haskell/test.sh index 59aa8b2f..d0af750a 100755 --- a/lib/haskell/test.sh +++ b/lib/haskell/test.sh @@ -56,6 +56,7 @@ for FILE in "${FILES[@]}"; do (load "lib/haskell/match.sx") (load "lib/haskell/eval.sx") (load "lib/haskell/map.sx") +(load "lib/haskell/set.sx") $INFER_LOAD (load "lib/haskell/testlib.sx") (epoch 2) @@ -100,6 +101,7 @@ EPOCHS (load "lib/haskell/match.sx") (load "lib/haskell/eval.sx") (load "lib/haskell/map.sx") +(load "lib/haskell/set.sx") $INFER_LOAD (load "lib/haskell/testlib.sx") (epoch 2) diff --git a/plans/haskell-completeness.md b/plans/haskell-completeness.md index 8f16f145..7ef38acb 100644 --- a/plans/haskell-completeness.md +++ b/plans/haskell-completeness.md @@ -209,7 +209,7 @@ No OCaml changes are needed. The view type is fully representable as an SX dict. - [x] API: `empty`, `singleton`, `insert`, `delete`, `member`, `fromList`, `toList`, `toAscList`, `size`, `null`, `union`, `intersection`, `difference`, `isSubsetOf`, `filter`, `map`, `foldr`, `foldl'`. -- [ ] Module wiring: `import Data.Set` / `import qualified Data.Set as Set`. +- [x] Module wiring: `import Data.Set` / `import qualified Data.Set as Set`. - [ ] Unit tests in `lib/haskell/tests/set.sx` (≥ 15 tests: empty, insert, member hit/miss, delete, fromList deduplication, union, intersection, difference, isSubsetOf). @@ -307,6 +307,16 @@ No OCaml changes are needed. The view type is fully representable as an SX dict. _Newest first._ +**2026-05-07** — Phase 12 module wiring: `import Data.Set`: +- New `hk-bind-data-set!` registers `Set.empty/singleton/insert/delete/ + member/size/null/union/intersection/difference/isSubsetOf` as Haskell + builtins. +- Import handler now dispatches on modname: `Data.Map` → `hk-bind-data-map!`, + `Data.Set` → `hk-bind-data-set!`. Default alias is now derived from the + modname suffix instead of being hardcoded `Map` (was a bug for `Data.Set`). +- `test.sh` and `conformance.sh` load `set.sx` after `map.sx`. +- Verified `Set.size`, `Set.member`, `Set.union`, `Set.insert` from Haskell. + **2026-05-07** — Phase 12 Data.Set full API: - Added `from-list`/`union`/`intersection`/`difference`/`is-subset-of`/ `filter`/`map`/`foldr`/`foldl` — all delegate to the corresponding