design: 22a — Decision 11 typeclasses (Haskell-lite, monomorphised, coherent)
This commit is contained in:
+130
@@ -10865,3 +10865,133 @@ directly: DESIGN.md typeclass section, instantiation strategy,
|
||||
schema nodes for `class` and `instance`, naming convention for
|
||||
monomorphised functions. Implementer iter (22b) follows after
|
||||
22a's design lands and is reviewed.
|
||||
|
||||
## 2026-05-09 — 22a: typeclass design
|
||||
|
||||
Trigger: 22a is the typeclass design iter queued in the previous
|
||||
JOURNAL entry. Per CLAUDE.md, design iters are orchestrator work
|
||||
done directly. This entry records the decisions and the reasoning;
|
||||
the canonical specification lives in `docs/DESIGN.md` as Decision 11.
|
||||
|
||||
The Feature-acceptance criterion (codified earlier the same day)
|
||||
was applied as the primary gate. Each of the five committed
|
||||
semantic axes traces to a single question: "would an LLM author
|
||||
unprompted produce code that uses this mechanism, AND does the
|
||||
mechanism measurably remove redundancy or improve correctness?"
|
||||
Where the answer was no, the mechanism was rejected.
|
||||
|
||||
### Five committed axes
|
||||
|
||||
1. **Haskell-lite scope** (multi-method, single-param, optional
|
||||
defaults, single-superclass). Multi-param classes were rejected
|
||||
because LLM authors do not produce them unprompted, and because
|
||||
they would require functional dependencies for tractable
|
||||
resolution. Full Haskell scope (assoc types, GADTs-style
|
||||
constraints) was rejected on the same grounds.
|
||||
|
||||
2. **Constraints in signatures: explicit and mandatory.** Constraint
|
||||
inference was rejected for the same reason mandatory mode
|
||||
annotations are mandatory (Decision 10): explicit annotation
|
||||
makes every commitment visible at the function boundary, so
|
||||
reading a signature requires no body-level reasoning. The "alles
|
||||
sichtbar" line of the project is preserved at this layer.
|
||||
|
||||
3. **Resolution: orphan-free coherence.** Modeled on Rust's coherence
|
||||
rule rather than Haskell's orphan-with-warning. The hard rule
|
||||
makes registry resolution unambiguous by construction; no
|
||||
`AmbiguousInstance` diagnostic exists. The trade — reduced
|
||||
flexibility for third-party instance authors — is acceptable
|
||||
because AILang's authoring surface is a single workspace, not
|
||||
an open package ecosystem.
|
||||
|
||||
4. **Defaults via explicit `default` keyword.** Haskell's
|
||||
convention of mixing default and required methods in the class
|
||||
body without syntactic distinction was rejected on visibility
|
||||
grounds. The `default` keyword makes "what must this instance
|
||||
implement" answerable from the class header alone. Same line
|
||||
as axis 2.
|
||||
|
||||
5. **Class-parameter kind: `*` only.** Higher-kinded class params
|
||||
were rejected because the abstraction they enable (`Functor`,
|
||||
`Monad`, `Applicative`) is not what an LLM author produces
|
||||
unprompted. The natural LLM pattern is `List.map`, `Tree.map`,
|
||||
`Option.map` as separate functions per type, which
|
||||
monomorphisation handles directly without class machinery. The
|
||||
kind-`*` restriction also removes the implementation cost of
|
||||
higher-kinded constraint resolution.
|
||||
|
||||
### Prelude scope
|
||||
|
||||
Three classes ship in the 22b Prelude: `Show`, `Eq`, `Ord`, with
|
||||
instances for the four primitive types (`Int`, `Float`, `Bool`,
|
||||
`String`). `Ord` declares `Eq` as superclass.
|
||||
|
||||
`print x` is rewired through `Show.show` at codegen — the one
|
||||
operator-routing change in 22b.
|
||||
|
||||
`==`, `<`, `<=`, `>`, `>=` stay primitive operators. Routing them
|
||||
through `Eq`/`Ord` would require migrating every existing fixture
|
||||
and would risk firing the bench gate during a feature iter.
|
||||
Operator routing is deliberately deferred to a later iter, gated
|
||||
on bench-stability.
|
||||
|
||||
`Num` is NOT in the Prelude. Arithmetic operators stay primitive
|
||||
and per-type. The LLM-natural pattern of distinct `Int` and
|
||||
`Float` arithmetic is preserved.
|
||||
|
||||
### What 22a does not commit to
|
||||
|
||||
- The exact textual form of monomorphised-symbol names (e.g.
|
||||
`show@Int` vs. `show#Int` vs. a hash-suffixed scheme). Naming
|
||||
is deterministic from `(method, type-hash)`; the textual form
|
||||
is fixed in 22b alongside the existing mangling scheme
|
||||
(DESIGN.md §"Mangling scheme").
|
||||
- The Form-B (prose) projection of `ClassDef` and `InstanceDef`.
|
||||
Prose-projector arms for the new nodes are 22b scope.
|
||||
- Mode-annotation defaults for class methods. Class method
|
||||
signatures are full FnSigs and carry mode annotations per
|
||||
Decision 10; conventions (likely `borrow` for read-only methods
|
||||
like `show`, `eq`, `lt`) settle in 22b.
|
||||
- Auto-derivation of instances. `deriving` is a future-iter option,
|
||||
gated on Feature-acceptance at proposal time.
|
||||
|
||||
### Why this iter is design-only
|
||||
|
||||
Per CLAUDE.md and the previous JOURNAL queue entry, 22a is design.
|
||||
No Rust crates change in this iter; no schema-floor commit; no
|
||||
bench corpus change. The iter ships a single edit to
|
||||
`docs/DESIGN.md` (Decision 11 added between Decision 10 and the
|
||||
Mangling-scheme section) and this JOURNAL entry. The schema and
|
||||
implementation land in 22b.
|
||||
|
||||
### Test state
|
||||
|
||||
288 / 0 / 3, unchanged. Documentation-only.
|
||||
|
||||
### Bench gates
|
||||
|
||||
Not re-run. No runtime, codegen, or check-time path is touched.
|
||||
|
||||
### JOURNAL queue (updated)
|
||||
|
||||
- **22b — typeclass implementer.** Schema floor for `ClassDef`,
|
||||
`InstanceDef`, `FnDef.type.constraints`. Workspace-load
|
||||
registry build with the three coherence/uniqueness/completeness
|
||||
checks. Class-schema validation (`KindMismatch`,
|
||||
`InvalidSuperclassParam`, `ConstraintReferencesUnboundTypeVar`).
|
||||
Typecheck arms for `MissingConstraint` and `NoInstance`.
|
||||
Monomorphisation pass + naming convention. Prelude module with
|
||||
`Show`/`Eq`/`Ord` and the four primitive instances. `print`
|
||||
rewiring through `Show.show`. End-to-end fixture exercising
|
||||
the full path. Bench gate at close.
|
||||
- **22c — typeclass corpus expansion (deferred).** User-defined
|
||||
classes/instances exercised by an example beyond the Prelude.
|
||||
Optional `deriving` shorthand if Feature-acceptance gate passes.
|
||||
- **Operator routing through Eq/Ord (deferred, no commitment).**
|
||||
Migrating `==`, `<`, etc. to class methods. Big-bang fixture
|
||||
refactor; gated on bench-stability and on a clear LLM-author
|
||||
benefit ("less ceremony" alone is not a benefit; needs a
|
||||
redundancy-removal claim).
|
||||
- **21'h, latency methodology, FnDef::synthetic, Boehm full
|
||||
retirement, closure-pair slab/pool, deferred richer integration
|
||||
paths.** Unchanged from 21'g.
|
||||
|
||||
Reference in New Issue
Block a user