Type-Safe Printf
Tutorial Video
Text description (accessibility)
This video demonstrates the "Type-Safe Printf" functional Rust example. Difficulty level: Expert. Key concepts covered: Functional Programming. C's `printf` is famously unsafe: `printf("%d", "hello")` compiles but causes undefined behavior at runtime. Key difference from OCaml: 1. **Macro vs. types**: Rust uses macros to parse format strings at compile time; OCaml encodes format strings as values of a GADT type that carries type information.
Tutorial
The Problem
C's printf is famously unsafe: printf("%d", "hello") compiles but causes undefined behavior at runtime. A type-safe printf encodes the format string's type signature in the type system, so passing the wrong type of argument is a compile error. This is one of the motivating examples for GADTs in OCaml and for HLists in Haskell, demonstrating how the type system can enforce format-argument correspondence at zero runtime cost.
🎯 Learning Outcomes
format_args! macro achieves a limited form of type-safe formatting at compile timeCode Example
#![allow(clippy::all)]
// Stub — awaiting conversion from OCaml source.Key Differences
format! macro achieves safety through a different (macro-based) mechanism.format! macro is closed (only built-in specifiers).OCaml Approach
OCaml's Printf.printf is genuinely type-safe via a clever encoding in the standard library:
Printf.printf "%d is %s\n" 42 "hello" (* type: int -> string -> unit *)
Printf.printf "%d is %s\n" "oops" (* type error at compile time *)
OCaml encodes format strings as GADTs where the phantom type encodes the argument sequence. The format6 type in OCaml's standard library is the result of decades of refinement to make this ergonomic.
Full Source
#![allow(clippy::all)]
// Stub — awaiting conversion from OCaml source.Deep Comparison
OCaml vs Rust: Type Safe Printf
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
Fmt<Int, Fmt<Str, Done>> and a format function that takes the matching HCons<i32, HCons<String, HNil>>.format_args! to verify that passing the wrong type for a {} placeholder is caught at compile time (not runtime).WHERE id = ? receives an integer, not a string.