{
  "id": 11124426,
  "title": "Typeclasses vs Modules",
  "url": "https://urgent.news/2026/10/01/typeclasses-vs-modules",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-10-01T05:13:31.000Z",
  "source": {
    "name": "Lobsters",
    "slug": "lobsters",
    "url": "https://sm2n.ca/articles/typeclasses-vs-modules/"
  },
  "original_language": "en",
  "account": "In recent discussions, a persistent confusion has arisen regarding the differences and similarities between module systems, exemplified in languages like OCaml, and typeclasses, found in languages such as Haskell and Rust. This article aims to clarify these concepts.\n\nTypeclasses primarily serve as a mechanism for ad-hoc polymorphism, also known as operator overloading or type-based dispatch. The objective is to enable the reuse of identical identifiers across various types. For instance, the \"+\" symbol might represent both integer and vector of floats addition, even if the latter is defined in an external library. Conversely, module systems provide modular abstraction, which can be associated with concepts like dependency injection, encapsulation, and information hiding. This approach allows for more efficient programming in the large by permitting explicit program decomposition, thereby facilitating recursive component breakdown.\n\nThe confusion often stems from the fact that, while emulation of typeclasses by modules is possible in many scenarios, it is usually not optimal. Typeclasses aim to maintain a consistent meaning for overloaded symbols, enabling the understanding of programs using a limited set of symbols. This is achieved through associating semantics with typeclasses, typically in the form of laws, property tests, or proof obligations.\n\nModule systems, on the other hand, facilitate ergonomic abstraction over program parts. By dividing the program into modules or structures, we can explicitly define their interactions. This modular decomposition allows for reduced reasoning efforts, as each module can hide certain aspects from other modules involved. Furthermore, parametrized modules, often referred to as functors, can encapsulate modules and instantiate them with other modules that adhere to a specific interface. This interface may also carry semantics, like laws, test suites, or proof obligations, to ensure the program's reliability and ease of testing.\n\nConsider a hypothetical example involving a StringMap type conforming to the Map.S signature from the standard library, with the key type specialized to String. This allows any code relying on the standard library's interface to utilize our custom map while ensuring correct key types. This approach exemplifies a \"set of functions\" methodology for program decomposition. Typeclass-driven programming, in contrast, views the program as a global type database, with functions interacting with different parts of this database based on scoping. Modules offer a more refined approach, allowing reasoning at larger program segments simultaneously.\n\nUltimately, while modules and typeclasses serve distinct purposes, both contribute to structured programming. Modules promote efficient reasoning at the function level, while typeclasses enable flexible and consistent polymorphism across diverse types.",
  "summary": null,
  "key_points": [],
  "editors_take": null,
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}