Coherence Rules
Tutorial Video
Text description (accessibility)
This video demonstrates the "Coherence Rules" functional Rust example. Difficulty level: Advanced. Key concepts covered: Functional Programming. If two crates independently implement the same trait for the same type, the compiler cannot decide which to use — this is the "coherence problem." Rust's orphan rule prevents this: you can only implement a trait for a type if at least one of the trait or the type is defined in your crate. Key difference from OCaml: 1. **Global coherence**: Rust enforces global coherence at compile time; OCaml relies on convention and explicit passing to avoid incoherence.
Tutorial
The Problem
If two crates independently implement the same trait for the same type, the compiler cannot decide which to use — this is the "coherence problem." Rust's orphan rule prevents this: you can only implement a trait for a type if at least one of the trait or the type is defined in your crate. This guarantees at most one implementation per (Trait, Type) pair globally, making trait resolution unambiguous. Understanding these rules prevents confusing "conflicting implementations" errors.
🎯 Learning Outcomes
Code Example
#![allow(clippy::all)]
// Stub — awaiting conversion from OCaml source.Key Differences
impl<T: Trait> OtherTrait for T) are powerful but interact subtly with coherence; OCaml's equivalent (functor application) is always explicit.OCaml Approach
OCaml has no orphan rule. Any module can implement any type class (module signature) for any type. This can lead to coherence problems in practice — two modules providing different compare functions for the same type. OCaml's solution is convention (use the canonical compare from the standard library) and the functor pattern (pass the implementation explicitly rather than resolving it globally).
Full Source
#![allow(clippy::all)]
// Stub — awaiting conversion from OCaml source.Deep Comparison
OCaml vs Rust: Coherence Rules
Overview
See the example.rs and example.ml files for detailed implementations.
Key Differences
| Aspect | OCaml | Rust |
|---|---|---|
| Type system | Hindley-Milner | Ownership + traits |
| Memory | GC | Zero-cost abstractions |
| Mutability | Explicit ref | mut keyword |
| Error handling | Option/Result | Result<T, E> |
See README.md for detailed comparison.
Exercises
impl Display for Vec<i32> and observe the error, then fix it with a newtype.impl<T: Clone + Debug> Describable for T and verify it applies to i32, String, and a custom struct.i32 and a custom type in the same crate and verify the compiler resolves calls correctly.