Phantom Type
Phantom types are type parameters in a data type that appear in the definition but not in the constructors, allowing additional static information to be encoded at the type level without affecting runtime representation. They are useful for enforcing invariants, such as distinguishing between different units of measurement or states of a resource, with all type checking performed at compile time.
Background
- **Phantom types** are type parameters in a generic type (like `data Foo a`) that appear in the type definition but are *not used* in any of its data constructors. They exist only at the type level, not at runtime.
- Haskell's strong static type system lets phantom types encode extra constraints or "tags" (e.g., units of measure, permission levels, or currency) without runtime overhead. The phantom parameter is erased at compile time.
- Classic examples: distinguishing `Distance Meters` from `Distance Feet` using the same internal representation, or a `FormState` type that allows only valid transitions (e.g., a "draft" form cannot be submitted as "final" without going through "review").
- Phantom types are a compile-time technique: invalid programs fail to type-check, but valid ones incur zero extra runtime cost. They are a key example of Haskell's ability to "make illegal states unrepresentable".