ExamplesBy LevelBy TopicLearning Paths
147 Advanced

Type Erasure

Functional Programming

Tutorial Video

Text description (accessibility)

This video demonstrates the "Type Erasure" functional Rust example. Difficulty level: Advanced. Key concepts covered: Functional Programming. Type erasure deliberately discards type information to enable heterogeneous collections, plugin systems, and dynamic dispatch. Key difference from OCaml: 1. **Explicit vs. implicit**: Rust requires explicit `Box<dyn Trait>` to erase types; Java erases generics silently at compile time (unsound without reification).

Tutorial

The Problem

Type erasure deliberately discards type information to enable heterogeneous collections, plugin systems, and dynamic dispatch. Storing values of different concrete types together requires erasing their specific types and retaining only a common interface. This is the mechanism behind Java's generics, Rust's Box<dyn Trait>, OCaml's existential types, and Go's interface values. The cost is one pointer indirection per method call; the benefit is open extension and runtime flexibility.

🎯 Learning Outcomes

  • • Understand what type erasure means and when it is the right tool
  • • Learn Rust's primary erasure mechanisms: Box<dyn Trait>, Arc<dyn Trait>, and Box<dyn Any>
  • • See how Any + downcast_ref provides safe type recovery after erasure
  • • Compare Rust's explicit erasure with Java's implicit erasure and OCaml's approach
  • Code Example

    #![allow(clippy::all)]
    // Stub — awaiting conversion from OCaml source.

    Key Differences

  • Explicit vs. implicit: Rust requires explicit Box<dyn Trait> to erase types; Java erases generics silently at compile time (unsound without reification).
  • Safe downcast: Rust's downcast_ref::<T>() checks TypeId at runtime; OCaml's GADT pattern match handles this structurally without runtime type IDs.
  • Method availability: Rust's vtable only exposes the trait's methods; Box<dyn Any> exposes just downcast; OCaml's first-class modules expose whatever the module signature declares.
  • Ownership: Rust's Box<dyn Any> has unique ownership; Arc<dyn Any> enables shared ownership across threads; OCaml's GC handles all sharing automatically.
  • OCaml Approach

    OCaml erases types through:

  • GADT existentials: type any = Any : 'a -> any packs any value with its type erased
  • First-class modules: (module M : INTERFACE) erases the module identity
  • Obj.magic (unsafe, equivalent to Rust's transmute) — never use in production
  • OCaml's GC means erased values are always safely accessible; Rust's ownership system requires Box or Arc to heap-allocate erased values.

    Full Source

    #![allow(clippy::all)]
    // Stub — awaiting conversion from OCaml source.

    Deep Comparison

    OCaml vs Rust: Type Erasure

    Overview

    See the example.rs and example.ml files for detailed implementations.

    Key Differences

    AspectOCamlRust
    Type systemHindley-MilnerOwnership + traits
    MemoryGCZero-cost abstractions
    MutabilityExplicit refmut keyword
    Error handlingOption/ResultResult<T, E>

    See README.md for detailed comparison.

    Exercises

  • Build a TypeMap that stores at most one value per type: insert<T: 'static>(&mut self, val: T) and get<T: 'static>(&self) -> Option<&T>.
  • Implement a plugin system with trait Plugin { fn name(&self) -> &str; fn run(&self); } and a registry that stores Vec<Box<dyn Plugin>>.
  • Write fn erase_and_recover<T: Any>(val: T) -> Option<T> that boxes a value as Box<dyn Any> and then recovers it via downcast.
  • Open Source Repos