Skip to content

Prelude surface: classes, instances, and the value functions #94

Closed

Description

@biuld

Part of #76 (Phase 3). The highest-leverage library slice: 163 passing files are blocked on Prelude alone, more than every other missing module combined.

stdlib/lib/Prelude.purs is currently six declarations — pure, bind, discard, map, apply, runEffect over foreign import data Effect. The corpus expects the standard classes and instances.

Classes and instances

Show, Eq, Ord, Semigroup, Monoid, Functor, Apply, Applicative, Foldable, plus Boolean combinators, folds, and the String/Char/Number conversions the corpus uses.

Prerequisites this exposes

Each of these is Phase 2 work, and writing the library is the forcing function that finds the rest:

Constraint

Every addition compiles and executes under Wasmtime, not only type-checks. A Prelude that type-checks but cannot run does not recover a single passing file.

Acceptance

Prelude carries the classes and instances above, executes under Wasmtime, and the passing files blocked on Prelude fall toward zero.

Activity

  1. added
    gate:L6/M7Blocks runtime and the standard library (D-04 L6, M7)
    area:stdlibThe PureScript standard library under stdlib/lib
    on Oct 1, 2026
  2. biuld commented on Oct 3, 2026

    @biuld
    OwnerAuthor

    First slice landed in #128: Data.Function and the $/# application operators.

    What landed

    • Data.Function: apply, applyFlipped, const, flip, on, plus infixr 0 apply as $ and infixl 1 applyFlipped as #.
    • Prelude re-exports const, flip, $, # (the official list) with an explicit export list.
    • Two prerequisite fixes: a re-exported operator alias no longer requires its target's name (the purs rule), and CC's partial-application adapter now converts the parameters it leaves to the caller to the declaration's shapes.

    identity is deliberately not defined here: official re-exports it from Control.Category, so it belongs with the class hierarchy rather than as a private Data.Function.identity.

    Measured

    PSRS_ORACLE=annotations cargo test -p psrs-driver --test suite -- --ignored --nocapture

    Board Before After
    passing resolution 209/413 225/413
    missing library module 62 61
    P3 resolve 138 123
    P10 147 155
    P5 typecheck 35 40
    L1 / M2 / M3 / M4 / M5 / L6 904/908, 72/72, 34/48, 34/50, 51/92, 0/413 unchanged

    Board field

    The Corpus cases field is now 80: the measured number of passing files whose first blocker is a Prelude class or value name (the convention counts first blocking stage, so this is the latent recovery the issue's surface owns, not a change in the first-blocker total). The largest groups are <> 15, Monad 9, identity/show/Eq 7 each, negate 5, Functor 5, otherwise/&&/<$>/add 3 each, and singles for Semiring, Show, when, append, mod, between, and >>>.

    Remaining

    The class hierarchy and its instances (Semigroup/<> needs a string- and array-concatenation primitive), Show/logShow (needs number formatting and Data.Show), Eq/Ord and the arithmetic classes whose surface operators are currently Int-monomorphic intrinsics, and identity/Control.Category.

  3. added a commit that references this issue on Oct 3, 2026
  4. biuld commented on Oct 3, 2026

    @biuld
    OwnerAuthor

    Landed the first slice: Data.Semigroup and <> (PR #130).

    • stdlib/lib/Data/Semigroup.purs declares class Semigroup a where append :: a -> a -> a, infixr 5 append as <>, and the String, Unit, and Array a instances; Prelude re-exports class Semigroup, append, <>.
    • The compiler gains the arrayAppend primitive (HIR Intrinsic::ArrayAppend → Core ExprKind::ArrayAppend → CC AssignmentKind::ArrayAppend). Because the MIR ArrayNewDefault verifier enforces array-conversion invariants, a general ArrayNewSized allocator plus two element-copy loops lower it.
    • Tests: PSRS_REQUIRE_WASMTIME=1 cargo test -p psrs-driver --lib tests::semigroup (4 pass; Wasmtime execution for string/array append including a non-ASCII string, and right-associativity).

    Measured with PSRS_ORACLE=annotations cargo test -p psrs-driver --test suite -- --ignored --nocapture (2026-10-04):

    Board Before After
    L2 passing resolution 225/413 235/413
    L2 first-stage blockers 188 178
    L2 P3 / P10 123 / 155 113 / 160
    L6/M7 P5 typecheck / P8 / P6 40 / 11 / 3 43 / 12 / 4
    L4 34/50 35/50
    L5 NoInstanceFound 38/53 40/53 (aggregate 51/92)

    <> was the largest single P3 name (15 cases) and append blocked 2 more; all 17 now stop on a later stage, and 10 cases resolve past L2 (5 P10, 3 P5 typecheck, 1 P8, 1 P6). The board Corpus cases for this issue drops 80 → 70.

    Still open here: show/Show, Monad, Eq, identity, Functor/<$>, negate, and the rest of the class/value surface; assertEqual and logShow (shared with #95) still need Eq/Show.

  5. biuld commented on Oct 4, 2026

    @biuld
    OwnerAuthor

    Landed Data.Functor in #142 (merge commit 77c8745).

    class Functor, map, and <$> live in Data.Functor, with Array, Maybe, and Either instances. Prelude re-exports them and adds the Effect instance. That instance is the old effect-only map: creating the action does not run it.

    One PSRS_REQUIRE_WASMTIME=1 PSRS_ORACLE=annotations scoreboard on 2026-10-04, Wasmtime 49.0.2, purs 0.15.16:

    Board Before After
    passing resolution 270/413 276/413
    L3 35/48 36/48
    L4 35/50 35/50
    L5 53/80 53/79
    L6/M7 124/413 125/413

    All 125 runtime files exit 0. The added file is passing/3549.purs. failing/3549.purs now matches KindsDoNotUnify. failing/NewtypeInstance5.purs leaves the L5 board and fails in the newtype checker. L1 stays 904/908 and L2 failing stays 72/72.

    Functor and <$> are gone from the first-blocker names. Corpus cases is now 67: Monad 14, identity 9, _ 8, negate 6, Eq1 4, <<< 4, otherwise 3, && 3, when 2, mod 2, compare 2, and one each of between, P.identity, >>>, <*>, not, Apply, ||, Applicative, -, and Foo.Bar.

    #94 stays open.

  6. biuld commented on Oct 16, 2026

    @biuld
    OwnerAuthor

    The 2026-10-17 scoreboard no longer has a passing file whose first blocker is a missing Prelude name. Corpus cases moves from 67 to 0.

    L2 passing resolution is 403/413, with 0 missing-library blockers, reconfirmed on 2026-10-17 against the vendored corpus (PSRS_ORACLE=annotations, compiler 886cd82c). The 6 P3 files are DeclConflict, UnknownExport, ScopeConflict, and ExportConflict. This issue stays open; the field tracks the first-blocker count, and the class surface is not re-audited by this comment.

    Evidence: L2 and L6/M7 in docs/design/D-04-suite-roadmap.md, recorded by #145.

  7. biuld commented on Oct 18, 2026

    @biuld
    OwnerAuthor

    The class surface this issue owns is measured complete on the corpus: the 2026-10-17 L2 board first reported no passing file blocked on a Prelude name (Corpus cases 67 → 0), reconfirmed 2026-10-18 on master f5abccda (PR #148): passing resolution 403/413 with 0 missing-library blockers, and L6/M7 287/340 with no in-scope program's first blocker inside Prelude's surface. The corpus-facing classes landed across the phase's slices: Data.Function ($/#), Data.Semigroup (<>), Data.Show, Data.Eq/Data.Ord/Data.Semiring (intrinsic layer), Data.Functor, Data.Monoid, Data.Foldable, Data.Tuple, Data.Traversable, plus the official module surface in the vendored package (e556bf2f, 313 trusted modules). Residual library-foreign work (Test.Assert.checkThrows) is #95's Blocked row; broader class/fundep solver acceptance is #97 (closed) / #98 / #100's scope. Closing on the measured evidence.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:stdlibThe PureScript standard library under stdlib/libenhancementNew feature or requestgate:L6/M7Blocks runtime and the standard library (D-04 L6, M7)

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions