From ee74a396c5467f8ee5abcc95bace4880f56f49ed Mon Sep 17 00:00:00 2001 From: giles Date: Wed, 6 May 2026 23:28:19 +0000 Subject: [PATCH] =?UTF-8?q?haskell:=20Phase=208=20deriving=20Show=20?= =?UTF-8?q?=E2=80=94=20verify=20nested-paren=20behavior=20(+4=20tests,=201?= =?UTF-8?q?5/15)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- lib/haskell/tests/deriving.sx | 27 +++++++++++++++++++++++++-- plans/haskell-completeness.md | 15 +++++++++++++-- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/lib/haskell/tests/deriving.sx b/lib/haskell/tests/deriving.sx index 80115171..976ff333 100644 --- a/lib/haskell/tests/deriving.sx +++ b/lib/haskell/tests/deriving.sx @@ -30,6 +30,31 @@ ;; ─── Eq ────────────────────────────────────────────────────────────────────── +(hk-test + "deriving Show: nested ADT wraps inner constructor in parens" + (hk-deep-force + (hk-run + "data Tree = Leaf | Node Int Tree Tree deriving (Show)\nmain = show (Node 1 Leaf (Node 2 Leaf Leaf))")) + "Node 1 Leaf (Node 2 Leaf Leaf)") + +(hk-test + "deriving Show: Maybe Maybe wraps inner Just" + (hk-deep-force (hk-run "main = show (Just (Just 3))")) + "Just (Just 3)") + +(hk-test + "deriving Show: negative argument wrapped in parens" + (hk-deep-force (hk-run "main = show (Just (negate 3))")) + "Just (-3)") + +(hk-test + "deriving Show: list element does not need parens" + (hk-deep-force + (hk-run "data Box = Box [Int] deriving (Show)\nmain = show (Box [1,2,3])")) + "Box [1,2,3]") + +;; ─── combined Eq + Show ─────────────────────────────────────────────────────── + (hk-test "deriving Eq: same constructor" (hk-deep-force @@ -58,8 +83,6 @@ "data Color = Red | Green | Blue deriving (Eq)\nmain = show (Red /= Blue)")) "True") -;; ─── combined Eq + Show ─────────────────────────────────────────────────────── - (hk-test "deriving Eq Show: combined" (hk-deep-force diff --git a/plans/haskell-completeness.md b/plans/haskell-completeness.md index f561ca00..6b13dd38 100644 --- a/plans/haskell-completeness.md +++ b/plans/haskell-completeness.md @@ -103,9 +103,10 @@ No OCaml changes are needed. The view type is fully representable as an SX dict. (needs Char tagging — currently Char = Int by representation, ambiguous in show); `\n`/`\t` escape inside Strings. - [x] `show` Prelude binding calls `hk-show-val`; `print x = putStrLn (show x)`. -- [ ] `deriving Show` auto-generates proper show for record-style and +- [x] `deriving Show` auto-generates proper show for record-style and multi-constructor ADTs. Nested application arguments wrapped in parens: - if `show arg` contains a space, emit `"(" ++ show arg ++ ")"`. + if `show arg` contains a space, emit `"(" ++ show arg ++ ")"`. _Records + deferred — Phase 14._ - [ ] `showsPrec` / `showParen` stubs so hand-written Show instances compile. - [ ] `Read` class stub — just enough for `reads :: String -> [(a,String)]` to type-check; no real parser needed yet. @@ -286,6 +287,16 @@ No OCaml changes are needed. The view type is fully representable as an SX dict. _Newest first._ +**2026-05-06** — Phase 8 `deriving Show` nested constructor parens verified: +- The Phase 8 audit's precedence-based `hk-show-prec` already does the right + thing for `deriving Show`: each constructor arg is shown at prec 11, so any + inner constructor with args (or any negative number) gets parenthesised, while + nullary constructors and lists/tuples (whose own bracketing is unambiguous) + do not. Multi-constructor ADTs (e.g. `Tree = Leaf | Node …`) handled. + Records deferred to Phase 14. +- 4 new tests in `tests/deriving.sx` exercising nested ADT + Maybe-Maybe + + negative-arg + list-arg cases; suite is 15/15. + **2026-05-06** — Phase 8 `print` is `putStrLn (show x)` in prelude: - Added `print x = putStrLn (show x)` to `hk-prelude-src` and removed the standalone `print` builtin. `print` now resolves through the Haskell-level