diff --git a/lib/haskell/conformance.sh b/lib/haskell/conformance.sh index 6249f8fc..75c451df 100755 --- a/lib/haskell/conformance.sh +++ b/lib/haskell/conformance.sh @@ -20,7 +20,7 @@ if [ ! -x "$SX_SERVER" ]; then fi fi -PROGRAMS=(fib sieve quicksort nqueens calculator collatz palindrome maybe fizzbuzz anagram roman binary either primes zipwith matrix wordcount powers caesar runlength-str) +PROGRAMS=(fib sieve quicksort nqueens calculator collatz palindrome maybe fizzbuzz anagram roman binary either primes zipwith matrix wordcount powers caesar runlength-str showadt showio) PASS_COUNTS=() FAIL_COUNTS=() diff --git a/lib/haskell/tests/program-showadt.sx b/lib/haskell/tests/program-showadt.sx new file mode 100644 index 00000000..7a50dbcd --- /dev/null +++ b/lib/haskell/tests/program-showadt.sx @@ -0,0 +1,45 @@ +;; showadt.hs — `deriving (Show)` on a multi-constructor recursive ADT. +;; Source: classic exposition example, e.g. Real World Haskell ch.6. +;; +;; Exercises Phase 8: `deriving (Show)` on an ADT whose constructors recurse +;; into themselves; precedence-based paren wrapping for nested arguments; +;; `print` from the prelude (which is `putStrLn (show x)`). + +(define + hk-showadt-source + "data Expr = Lit Int | Add Expr Expr | Mul Expr Expr deriving (Show)\n\nmain = do\n print (Lit 3)\n print (Add (Lit 1) (Lit 2))\n print (Mul (Lit 3) (Add (Lit 4) (Lit 5)))\n") + +(hk-test + "showadt.hs — main prints three lines" + (hk-run-io hk-showadt-source) + (list "Lit 3" "Add (Lit 1) (Lit 2)" "Mul (Lit 3) (Add (Lit 4) (Lit 5))")) + +(hk-test + "showadt.hs — show Lit 3" + (hk-deep-force + (hk-run + "data Expr = Lit Int | Add Expr Expr | Mul Expr Expr deriving (Show)\nmain = show (Lit 3)")) + "Lit 3") + +(hk-test + "showadt.hs — show Add wraps both args" + (hk-deep-force + (hk-run + "data Expr = Lit Int | Add Expr Expr | Mul Expr Expr deriving (Show)\nmain = show (Add (Lit 1) (Lit 2))")) + "Add (Lit 1) (Lit 2)") + +(hk-test + "showadt.hs — fully nested Mul of Adds" + (hk-deep-force + (hk-run + "data Expr = Lit Int | Add Expr Expr | Mul Expr Expr deriving (Show)\nmain = show (Mul (Add (Lit 1) (Lit 2)) (Add (Lit 3) (Lit 4)))")) + "Mul (Add (Lit 1) (Lit 2)) (Add (Lit 3) (Lit 4))") + +(hk-test + "showadt.hs — Lit with negative literal wraps int in parens" + (hk-deep-force + (hk-run + "data Expr = Lit Int | Add Expr Expr | Mul Expr Expr deriving (Show)\nmain = show (Lit (negate 7))")) + "Lit (-7)") + +{:fails hk-test-fails :pass hk-test-pass :fail hk-test-fail} diff --git a/lib/haskell/tests/program-showio.sx b/lib/haskell/tests/program-showio.sx new file mode 100644 index 00000000..e940eeca --- /dev/null +++ b/lib/haskell/tests/program-showio.sx @@ -0,0 +1,36 @@ +;; showio.hs — `print` on various types inside a `do` block. +;; +;; Exercises Phase 8 `print x = putStrLn (show x)` and the IO monad's +;; statement sequencing. Each `print` produces one io-line. + +(define + hk-showio-source + "main = do\n print 42\n print True\n print False\n print [1,2,3]\n print (1, 2)\n print (Just 5)\n print Nothing\n print \"hello\"\n") + +(hk-test + "showio.hs — main produces 8 lines, all show-formatted" + (hk-run-io hk-showio-source) + (list "42" "True" "False" "[1,2,3]" "(1,2)" "Just 5" "Nothing" "\"hello\"")) + +(hk-test + "showio.hs — print Int alone" + (hk-run-io "main = print 42") + (list "42")) + +(hk-test + "showio.hs — print list of Maybe" + (hk-run-io "main = print [Just 1, Nothing, Just 3]") + (list "[Just 1,Nothing,Just 3]")) + +(hk-test + "showio.hs — print nested tuple" + (hk-run-io "main = print ((1, 2), (3, 4))") + (list "((1,2),(3,4))")) + +(hk-test + "showio.hs — print derived ADT inside do" + (hk-run-io + "data Color = Red | Green | Blue deriving (Show)\nmain = do { print Red; print Green; print Blue }") + (list "Red" "Green" "Blue")) + +{:fails hk-test-fails :pass hk-test-pass :fail hk-test-fail} diff --git a/plans/haskell-completeness.md b/plans/haskell-completeness.md index 46902752..c1f19f6f 100644 --- a/plans/haskell-completeness.md +++ b/plans/haskell-completeness.md @@ -115,7 +115,7 @@ No OCaml changes are needed. The view type is fully representable as an SX dict. deriving Show on multi-constructor type, nested constructor parens). _Char tests deferred: Char = Int representation; show on a Char is currently `"97"` not `"'a'"`._ -- [ ] Conformance programs: +- [x] Conformance programs: - `showadt.hs` — `data Expr = Lit Int | Add Expr Expr | Mul Expr Expr` with `deriving Show`; prints a tree. - `showio.hs` — `print` on various types in a `do` block. @@ -289,6 +289,14 @@ No OCaml changes are needed. The view type is fully representable as an SX dict. _Newest first._ +**2026-05-07** — Phase 8 conformance: `showadt.hs` + `showio.hs` (both 5/5): +- `program-showadt.sx`: `deriving (Show)` on the classic `Expr = Lit | Add | Mul` + recursive ADT; tests `print` on three nested expressions and inline `show` + spot-checks (negative literal wrapped in parens; fully nested Mul of Adds). +- `program-showio.sx`: `print` on Int, Bool, list, tuple, Maybe, String, ADT + inside a `do` block; verifies one io-line per `print`. +- Both added to `PROGRAMS` in `conformance.sh`. Phase 8 conformance complete. + **2026-05-07** — Phase 8 `tests/show.sx` expanded to full audit coverage (26/26): - 16 new direct `show` tests: Int (positive + negative), Bool (T/F), String, list of Int, empty list, pair tuple, triple tuple, Maybe Nothing, Maybe Just,