Labelled preorders and implicit coercions › Approaches to the diamond problem(s) in existing systems [01HE]
- September 30, 2025
- Jon Sterling
Labelled preorders and implicit coercions › Approaches to the diamond problem(s) in existing systems [01HE]
- September 30, 2025
- Jon Sterling
Here I outline some (but not all) existing approaches to dealing with implicit coercions, multiple inheritance, and the various diamond problems.
1. Coherent type classes in Haskell [01HF]
- September 30, 2025
- Jon Sterling
1. Coherent type classes in Haskell [01HF]
- September 30, 2025
- Jon Sterling
Haskell employs a syntactic condition to ensure that type classes instances do not overlap, leading to a global coherence property. Practice in the Haskell community has shown that it is possible (but painful) to develop coherent hierarchies. Many advanced libraries will activate a language extension to allow overlapping instances, which renders the hierarchy incoherent.
2. Fast but incoherent type classes in Lean [01HG]
- September 30, 2025
- Jon Sterling
2. Fast but incoherent type classes in Lean [01HG]
- September 30, 2025
- Jon Sterling
Type class hierarchies arising in mathematics tend to be unavoidably incoherent; therefore, systems like Lean implement a backtracking type class resolver and are therefore confronted with the second diamond problem above. The Lean team have discovered an algorithm that they call Tabled Typeclass Resolution that mitigates the exponential blow-up using ideas from logic programming.
The state of affairs for Lean is, then, that type class resolution is pretty fast but the actual resolution of coercions is in theory non-deterministic; in reality, it does the same thing every time (so far as I know), but there is no guarantee about which coercions it is choosing.
3. Coherent locale hierarchies in Isabelle [01HH]
- September 30, 2025
- Jon Sterling
3. Coherent locale hierarchies in Isabelle [01HH]
- September 30, 2025
- Jon Sterling
Locales provide a coherent way to organise mathematical hierarchies. The problems that lead type class hierarchies to become incoherent do not seem to apply to locale hierarchies, I think, because the resolution of the locale’s operations is name-based rather than component-based. (I am not completely certain that this is the full story, but it seems like it is part of the story.)
One way to think about locales and the reason they can remain coherent is by analogy with Haskell’s newtype trick, which Haskell programmers use liberally to maintain coherence, but taken to its logical conclusion. Instead of generating a fresh copy of a type in order to indicate its intended role in the type class hierarchy, Isabelle doesn’t hang identity on the type at all and instead just starts with the name that carries intentional force.
The coherence of the locale hierarchy in Isabelle is checked when activating a locale as a local theory. Here, an algorithm called “roundup” reaches through the entire locale inheritance graph and brings all the needful operations into scope, and if there is a clash (two names pointing to different things), this results in an error. Such a clash always corresponds to a failure of coherence, and conversely, failures of coherence will always lead to such clashes.
4. Coherent coercions in Rocq [01HI]
- September 30, 2025
- Jon Sterling
4. Coherent coercions in Rocq [01HI]
- September 30, 2025
- Jon Sterling
Rocq has a coercion mechanism, which checks coherence and warns users when they are installing incoherent coercions. Coercions are most used in the world of Mathematical Components in combination with the canonical structures feature, which simulates type-class like features using something like unification hints (to my knowledge).
The algorithm used in Rocq was created by Kazuhiko Sakaguchi and described in the PhD thesis Refinement and extension of mathematical structures in proof assistants based on dependent type theory. The idea here is to maintain the reflexive-transitive closure (path category) of the coercion graph at all times; when inserting a new coercion, you check a generating class of diamonds for coherence and then add all the induced paths. Coherence then ensures that the path category is a preorder, with a functorial embedding into the syntactic category of the language under consideration.