Skip to content

Add Effect.Console.logShow over the library Show - #138

Merged
biuld merged 1 commit into
masterfrom
stdlib/effect-console-log-show
Oct 4, 2026
Merged

biuld merged 1 commit into
masterfrom
stdlib/effect-console-log-show

Conversation

@biuld

@biuld biuld commented Oct 4, 2026

Copy link
Copy Markdown
Owner

What

Effect.Console.logShow :: forall a. Show a => a -> Effect Unit, defined as
log (show value). It adds no I/O and no second stringifier: the rendering is
the library's Show, and the destination is still the one WASI.Console.log
decides. This is the wrapper #95 has been holding since the Show class landed.

Test.Assert.assertEqual/assertEqual' stay absent, and stdlib/lib/Test/Assert.purs
now records why. It is no longer a missing class — Eq and Show are both
declared — it is a compiler defect (#137).

Measured

PSRS_REQUIRE_WASMTIME=1 PSRS_ORACLE=annotations cargo test -p psrs-driver --test suite -- --ignored --nocapture, at 071fb11 plus this slice:

Board Before After
L1 parse 904/908 904/908
L2 failing 72/72 72/72
L3 35/48 35/48
L4 35/50 35/50
L5 53/80 53/80
passing resolved 253/413 270/413
M7 first blockers missing 53, P10 177, P3 103, P5t 42, P5k 17, P8 13, P6 4, P0 4 missing 53, P10 187, P3 86, P5t 46, P5k 17, P8 14, P6 6, P0 4
L6/M7 runtime 0/413 0/413

logShow was the largest single P3 name blocker at 24 cases (19 reported as
"logShow is not exported by the imported module"). Of those, 17 resolve past
L2
; the other 7 stop at the next P3 name, which nothing shadowed before:
Monad and compare 2 each, and negate, not, and _ 1 each. The 17 land at
later stages as 10 P10, 4 P5 typecheck, 1 P8, and 2 P6.

The assertEqual blocker

The official signature is

assertEqual' :: forall a. Eq a => Show a => String -> { actual :: a, expected :: a } -> Effect Unit

and this compiler elaborates Eq a against the record rather than a, so the
wanted constraint comes out as Eq { actual :: a, expected :: a }. Probes that
separate this from record syntax:

Signature Result
forall a. Eq a => a -> Int accepted
forall a. String -> { actual :: a, expected :: a } -> Int (no constraint) accepted
forall a. { actual :: a, expected :: a } -> a — field access accepted
forall a. { actual :: a, expected :: a } -> a — record pattern accepted
forall a. Eq a => { actual :: a, expected :: a } -> Int rejected
the same behind a type synonym for the record rejected

So the record with quantified fields is fine on its own and both destructuring
forms work; only the constraint combined with the record fails. Filed as #137 with
the reproduction. Changing the argument shape would change the API the corpus
calls, so the two functions stay out — 2 passing cases remain blocked.

Validation

cargo fmt --all --check
cargo clippy --workspace --all-targets -- -D warnings
PSRS_REQUIRE_WASMTIME=1 cargo test --workspace

New execution test tests::assertions::log_show_writes_the_library_rendering
asserts the six renderings under Wasmtime, so a second stringifier would fail it.
Its negative case is written 0 - 7 rather than - 7 because unary minus still
resolves through a negate this library does not declare.

Board

Corpus cases recounted from the run above: #95 19 → 2, #94 70 → 77, #96 12 → 17,
#124 25 → 27. #94 goes up because the 7 cases that stopped on logShow stop on a
Prelude name #94 also owns.

`logShow :: forall a. Show a => a -> Effect Unit` is `log` of
`Data.Show.show`, so it adds no I/O and no second stringifier: the
rendering is the library's `Show` and the destination is still the one
`WASI.Console.log` decides.

`logShow` was the largest single P3 name blocker at 24 cases, 19 of them
reported as "`logShow` is not exported by the imported module". Measured
with `PSRS_REQUIRE_WASMTIME=1 PSRS_ORACLE=annotations cargo test -p
psrs-driver --test suite -- --ignored --nocapture` at `071fb11` plus this
slice, `passing` resolution moves 253/413 to 270/413. Of the 24, 17
resolve past L2 and 7 stop at the next P3 name, which is visible for the
first time now that nothing shadows it: `Monad` and `compare` 2 each, and
`negate`, `not`, and `_` 1 each. The 17 land at later stages as 10 P10,
4 P5 typecheck, 1 P8, and 2 P6.

`Test.Assert.assertEqual`/`assertEqual'` stay absent, and the reason is a
compiler defect rather than a missing class. Both classes are declared,
but the official signature is `forall a. Eq a => Show a => String ->
{ actual :: a, expected :: a } -> Effect Unit`, and a constraint whose
quantified variable appears inside a record type is elaborated with the
*record* as the constraint's argument, so `Eq a` is wanted for
`{ actual :: a, expected :: a }`. #137 carries the reproduction and the
probes that separate this from record syntax. Approximating the argument
shape would change the API the corpus calls, so the two functions stay
out; that leaves 2 `passing` cases blocked.

D-04 now carries one consistent measurement of all five boards rather than
three independent `6f66524` figures that were not additive. The L5 row
said 84; the per-code totals sum to 80 and the remeasurement confirms 80.
@biuld
biuld merged commit 98c0be6 into master Oct 4, 2026
2 checks passed
@biuld
biuld deleted the stdlib/effect-console-log-show branch October 4, 2026 05:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant