Traits are a local maximum

Title and language nitpicks

  • Several comments note that “maxima” is plural and “maximum” is singular, and that the article’s title is grammatically off.
  • Some discussion on stylistic choices in the post (fancy verbs, “proselytize”), with mixed views: some like rich vocabulary, others say good technical writing should feel simple and accessible.

Traits, type classes, ML modules, implicits

  • Core comparison: Rust/Haskell traits/typeclasses vs ML-style modules vs implicits.
  • Traits: instances are unnamed and resolved from (type, trait), which is ergonomic but forces coherence.
  • ML modules: implementations are named; more annotation, but clearer and more explicit.
  • Implicits (as in the article) are framed as “local coherence”: instance selection by lexical proximity, trading off global correctness guarantees for flexibility.

Coherence, orphan implementations, and correctness

  • Strong focus on the “orphan rule” (no impl of foreign trait for foreign type) and global coherence.
  • Many argue coherence is essential for correctness: e.g., hashing or set ordering must be consistent across crates, or you can corrupt collections.
  • Multiple proposals surface:
    • Import/export of orphan impls explicitly.
    • Restrict orphans to binaries or special “glue” crates.
    • Allow “impl if not already implemented” / warnings instead of errors.
  • Pushback: these lead to unpredictable behavior when dependencies change; people value Rust’s lack of linker-style surprises.

Workarounds and alternative designs

  • Newtypes are widely discussed as the sanctioned workaround; seen as correct but often boilerplate-heavy. Ideas: better ergonomics (e.g., Deref, deriving) without semantic surprises.
  • Other ecosystem examples: Haskell’s orphans + warnings, Julia’s “type piracy,” Nim’s UFCS and mixins, dependently-typed implicits as explicit parameters.
  • Some suggest traits as just sets of functions (no impls), relying on normal name resolution; critics note this still doesn’t solve sharing implementations, only signatures.

Ad hoc polymorphism remains hard

  • Several commenters describe ad hoc polymorphism (traits/typeclasses/implicits) as an unsolved tradeoff space rather than something with a clear “right” answer.
  • General sentiment: Rust’s current trait system is a “local maximum” many are happy with, but there’s clear demand for more ergonomic cross-crate “glue,” especially for things like serialization and database traits.