6.5. Type Classes
A type class is a structure of operations parameterised by one or more arguments, usually types. A class declares the operations, an instance supplies them for particular arguments, and instance resolution finds the right instance from those arguments whenever a function requests one with [C α]. Some classes are indexed by more than a type, and Std.Associative op of Lecture 4 is indexed by an operation. This is the mechanism Lecture 2 used to give ∈ its meaning through a Membership instance and Lecture 4 used to register add as associative and commutative for ac_rfl.
namespace Func
class Size (α : Type) where
size : α → ℕ
instance {α : Type} : Size (List α) where
size xs := xs.length
instance {α : Type} : Size (Option α) where
size
| none => 0
| some _ => 1
def usize {α : Type} [Size α] (a : α) : ℕ :=
Size.size a
end Func
The function usize names no instance. It requests [Size α], and resolution supplies the list instance or the option instance according to the type at the call site.
6.5.1. Examples
The examples below declare instances, watch resolution choose by type, and name the classes the earlier lectures used.
Example 1. The list instance measures a list by its length.
namespace Func
#eval usize [1, 2, 3]
end Func
Example 2. The option instance measures presence, 1 or 0.
namespace Func
#eval usize (some 7)
end Func
Example 3. An instance may depend on other instances, as a product depends on its factors.
namespace Func
instance {α β : Type} [Size α] [Size β] :
Size (α × β) where
size p := Size.size p.1 + Size.size p.2
#eval usize ([1, 2], some 3)
end Func
Example 4. Resolution chooses the instance from the type alone, which inferInstance makes explicit.
namespace Func
#check (inferInstance : Size (List ℕ))
end Func
Example 5. A class may give a field a default, which an instance may leave untouched or override.
namespace Func
class Greet (α : Type) where
label : String := "item"
instance : Greet Bool where
instance : Greet ℕ where
label := "number"
#eval (Greet.label (α := Bool))
#eval (Greet.label (α := ℕ))
end Func
Example 6. The ∈ of Lecture 2 is the method of the Membership class, resolved by the type of the container.
#check @Membership.mem
Example 7. Lean can build some instances automatically with deriving, here equality and a textual form for a finite type.
namespace Func
inductive Coin where
| heads
| tails
deriving Repr, DecidableEq
#eval Coin.heads
end Func
Example 8. The derived equality lets decide settle a concrete disequality.
namespace Func
example : Coin.heads ≠ Coin.tails := ⊢ Coin.heads ≠ Coin.tails All goals completed! 🐙
end Func
Example 9. A class method carries an implicit instance argument, which #check displays.
namespace Func
#check @Size.size
end Func
Example 10. The associativity and commutativity that ac_rfl consulted in Lecture 4 are instances of Std.Associative and Std.Commutative.
#check @Std.Associative
#check @Std.Commutative