diff --git a/lib/haskell/eval.sx b/lib/haskell/eval.sx index 430bfdc4..df6584fc 100644 --- a/lib/haskell/eval.sx +++ b/lib/haskell/eval.sx @@ -789,6 +789,26 @@ (dict-set! hk-vfs (hk-force path) (hk-force contents)) (list "IO" (list "Tuple")))) 2)) + (dict-set! env "sqrt" (hk-mk-builtin "sqrt" (fn (x) (sqrt x)) 1)) + (dict-set! + env + "floor" + (hk-mk-builtin "floor" (fn (x) (floor x)) 1)) + (dict-set! + env + "ceiling" + (hk-mk-builtin + "ceiling" + (fn (x) (let ((f (floor x))) (if (= x f) f (+ f 1)))) + 1)) + (dict-set! + env + "round" + (hk-mk-builtin "round" (fn (x) (round x)) 1)) + (dict-set! + env + "truncate" + (hk-mk-builtin "truncate" (fn (x) (truncate x)) 1)) (let ((--sx-to-hk-- (fn (lst) (if (empty? lst) (list "[]") (list ":" (first lst) (--sx-to-hk-- (rest lst)))))) (--words-- diff --git a/lib/haskell/tests/numerics.sx b/lib/haskell/tests/numerics.sx index 10e05d6a..1b467fc7 100644 --- a/lib/haskell/tests/numerics.sx +++ b/lib/haskell/tests/numerics.sx @@ -138,4 +138,22 @@ (hk-deep-force (hk-run "main = show (negate 3.14)")) "-3.14") +(hk-test "sqrt 16 = 4" (hk-deep-force (hk-run "main = sqrt 16")) 4) + +(hk-test "floor 3.7 = 3" (hk-deep-force (hk-run "main = floor 3.7")) 3) + +(hk-test "ceiling 3.2 = 4" (hk-deep-force (hk-run "main = ceiling 3.2")) 4) + +(hk-test + "ceiling on whole = self" + (hk-deep-force (hk-run "main = ceiling 4")) + 4) + +(hk-test "round 2.6 = 3" (hk-deep-force (hk-run "main = round 2.6")) 3) + +(hk-test + "truncate -3.7 = -3" + (hk-deep-force (hk-run "main = truncate (negate 3.7)")) + -3) + {: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 f3a3f9ed..3ae70ee3 100644 --- a/plans/haskell-completeness.md +++ b/plans/haskell-completeness.md @@ -160,7 +160,7 @@ No OCaml changes are needed. The view type is fully representable as an SX dict. ints (`1.0e10` → `"10000000000"`) because our system can't distinguish `42` from `42.0` — both are SX numbers where `integer?` is true. Existing tests like `show 42 = "42"` rely on this rendering. Documented in `numerics.sx`._ -- [ ] Math builtins: `sqrt`, `floor`, `ceiling`, `round`, `truncate` — call +- [x] Math builtins: `sqrt`, `floor`, `ceiling`, `round`, `truncate` — call the corresponding SX numeric primitives. - [ ] `Fractional` typeclass stub: `(/)`, `recip`, `fromRational`. - [ ] `Floating` typeclass stub: `pi`, `exp`, `log`, `sin`, `cos`, `(**)` @@ -301,6 +301,12 @@ No OCaml changes are needed. The view type is fully representable as an SX dict. _Newest first._ +**2026-05-07** — Phase 10 math builtins (sqrt/floor/ceiling/round/truncate): +- Inserted in the post-prelude `begin` block so they override the prelude's + identity stubs. `ceiling` is the only one needing a definition (SX doesn't + ship one — derived from `floor`). `sqrt`, `floor`, `round`, `truncate` + thunk through to SX primitives. 6 new tests in `numerics.sx` (now 28/28). + **2026-05-07** — Phase 10 Float display through `hk-show-val`: - Added `hk-show-num` and `hk-show-float-sci` helpers in `eval.sx`. Number formatting: `integer?` → decimal (covers all whole-valued numbers, both ints