Zulip Chat Archive
Stream: new members
Topic: Need help with improving a basic Lean example
Rick van Oosterhout (Feb 04 2025 at 20:57):
I worked out a basic concept that I want to use to explain some of the concepts of dependent type theory, calculus of (inductive) constructions and Lean, using some analogies with Lego's. I came up with the following definitions and managed to set up a simple theorem and prove it. However, I would like to have some feedback from more experienced Lean users.
Mainly looking for tips to expand the analogy to explain other relevant topics, if you think I missed one. Besides, I would like to get any feedback on the Lean definitions and theorems, on how things could be simplified or clarified further. Any suggestions on my code are welcome, as I want to learn the best practices for Lean.
open Nat
-- Use natural numbers
abbrev ℕ := Nat
-- Basic brick type
inductive Lego : Type
  | brick
  | plate
namespace Lego
-- Function that adds computation to the tower
def brickHeight : Lego → ℕ
  | brick => 3
  | plate => 1
#eval brickHeight plate
#eval brickHeight brick
-- Define the inductive type for a Lego Tower
inductive LegoTower : Type
  | base : LegoTower  -- Base case: base plate
  | stack : Lego → LegoTower → LegoTower  -- Inductive step: add a lego
namespace LegoTower
def t1 : LegoTower := base
def t2 : LegoTower := stack plate base
def t3 : LegoTower := stack plate (stack brick base)
-- Define a dependent type for a tower with exactly 'n' lego's
inductive nLegoTower : ℕ → Type
  | nBase : nLegoTower 0  -- A tower of height 0 (base case)
  | nStack : Lego → (nLegoTower n) → nLegoTower (n + 1)  -- Add a lego
namespace nLegoTower
-- Example of a tower with exactly 3 lego's
def nLegoTower3 : nLegoTower 3 := (nStack brick (nStack plate (nStack brick (nBase))))
def nToLegoTower {n: ℕ} : nLegoTower n → LegoTower
  | nBase => base
  | nStack br rest => stack br (nToLegoTower rest)
-- Tower height
def recTowerHeight (tower : LegoTower) :=
  match tower with
  | base => 0
  | stack br rest => brickHeight br + recTowerHeight rest
def towerHeight (tower : LegoTower) : ℕ := recTowerHeight tower
#eval towerHeight t1
#eval towerHeight t2
#eval towerHeight t3
#eval towerHeight (nToLegoTower nLegoTower3)
-- Basic proof that 'towerHeight (nToLegoTower t) ≤ 3 * n'
-- Lemma that any brick ≤ 3
theorem brick_height_limit (b : Lego) : brickHeight b ≤ 3 := by
  induction b <;> (rw [brickHeight]; simp)
-- Lemma for the inductive step below
theorem n_tower_max_height_ind (n : ℕ) (t : nLegoTower m) :
  towerHeight (nToLegoTower t) ≤ 3 * n → brickHeight b + towerHeight (nToLegoTower t) ≤ 3 * n + 3 := by
    intro h
    calc
      brickHeight b + towerHeight (nToLegoTower t)
        ≤ 3 + towerHeight (nToLegoTower t) := by apply Nat.add_le_add_right (brick_height_limit b)
      _ ≤ 3 + 3 * n := by apply Nat.add_le_add_left h
      _ = 3 * n + 3 := by rw [Nat.add_comm]
-- Complete proof
theorem n_tower_max_height (t : nLegoTower n) : towerHeight (nToLegoTower t) ≤ 3 * n := by
  induction t with
  | nBase =>
    -- Simplify case
    rw [nToLegoTower, towerHeight, recTowerHeight, Nat.mul_zero, Nat.le_zero_eq]
  | nStack b rt ih =>
    -- Move out brickheight b
    rw [nToLegoTower, towerHeight, recTowerHeight, ← towerHeight, Nat.mul_add, Nat.mul_one]
    -- Solve using lemma
    exact n_tower_max_height_ind _ rt ih
Last updated: May 02 2025 at 03:31 UTC