HASKELL / CHAPTER 11
Type classes, newtypes, and laws
AdvancedExpress capabilities while preserving domain distinctions.
By the end of this chapter
- Read capability constraints
- Use newtype for a distinct domain type
- Separate compiler checks from semantic laws
The idea
A type class describes a capability implemented by types, such as equality or ordering. A constrained function can request that capability without selecting one concrete representation. Instances supply operations, while class laws describe relationships those operations should satisfy. The compiler checks types, but it does not prove that a custom equality relation is reflexive, symmetric, or transitive.
Newtype gives a distinct type around one representation, useful when two quantities should not be interchangeable merely because both are integers. Deriving suitable standard instances can preserve the wrapped representation’s established behavior. Keep unsafe constructors or conversions behind a deliberate boundary when the domain imposes additional invariants. Do not assume a newtype automatically validates range or units at runtime.
newtype UserId = UserId Integer deriving (Eq, Show)
main = do
print (UserId 3 == UserId 3)
print (UserId 3 == UserId 4)True False
The derived equality compares wrapped values while UserId remains a distinct type from an ordinary Integer.
Try it yourself
Define distinct user and order identifier types and show an invalid accidental interchange.
Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.
CHECK YOUR UNDERSTANDING