6.4. Structures and Records
A structure is an inductive type with a single constructor and named fields, and Lean derives a projection for each field. It is the natural shape for a record of related values. The anonymous constructor ⟨…⟩, the field syntax { … }, and the update syntax { r with … } all build or modify a structure, and extends builds a larger structure on a smaller one. The And.intro of Lecture 1 and the pair of Lecture 3 are themselves single-constructor structures.
namespace Func
structure Segment where
lo : ℤ
hi : ℤ
def width (s : Segment) : ℤ := s.hi - s.lo
structure NamedSegment extends Segment where
name : String
end Func
A NamedSegment carries the two fields of Segment and one more, and a projection reaches the inherited fields directly.
6.4.1. Examples
The examples below build, project, update, and extend records.
Example 1. A projection reads a field, and width computes from two of them.
namespace Func
def seg1 : Segment := { lo := 1, hi := 5 }
example : width seg1 = 4 := ⊢ width seg1 = 4 All goals completed! 🐙
end Func
Example 2. The field syntax { … } and the anonymous constructor ⟨…⟩ build the same value.
namespace Func
def seg2 : Segment := ⟨1, 5⟩
example : seg1 = seg2 := rfl
end Func
Example 3. The update syntax { r with … } copies a record and changes one field.
namespace Func
def widen (s : Segment) : Segment :=
{ s with hi := s.hi + 1 }
example : (widen seg1).hi = 6 := ⊢ (widen seg1).hi = 6 All goals completed! 🐙
end Func
Example 4. extends adds a field, and the inherited fields stay accessible.
namespace Func
def ns1 : NamedSegment :=
{ lo := 0, hi := 2, name := "a" }
example : ns1.lo = 0 := ⊢ ns1.lo = 0 All goals completed! 🐙
end Func
Example 5. The new field is reached like any other.
namespace Func
example : ns1.name = "a" := rfl
end Func
Example 6. A field may itself be a function, and the projection recovers it.
namespace Func
structure Handler where
run : ℕ → ℕ
def dbl : Handler := { run := fun n => n + n }
example : dbl.run 3 = 6 := rfl
end Func
Example 7. Building a record and projecting a field returns the field, by computation.
namespace Func
example : (⟨1, 5⟩ : Segment).lo = 1 := rfl
end Func
Example 8. A function of a record computed from its fields.
namespace Func
def midpoint (s : Segment) : ℤ :=
(s.lo + s.hi) / 2
example : midpoint ⟨0, 4⟩ = 2 := ⊢ midpoint { lo := 0, hi := 4 } = 2 All goals completed! 🐙
end Func
Example 9. Prod is the canonical two-field structure, with Prod.fst and Prod.snd its projections.
example : (Prod.fst (3, 5) : ℕ) = 3 := rfl
Example 10. The And.intro of Lecture 1 is a two-field structure, and the anonymous constructor builds it.
example (a b : Prop) (ha : a) (hb : b) : a ∧ b :=
⟨ha, hb⟩