Zulip Chat Archive

Stream: general

Topic: structures with contracts


Matthew Pocock (Sep 07 2023 at 22:40):

Say I have a type

structure OrdPair
  lower : Nat
  higher : Nat

I want this struct to have the additional contractual guarantee that lower < higher. So can I have the struct carry the proof somehow? Something like this?

structure OrdPair
  lower : Nat
  higher : Nat
  is_ord: lower < higher

Is this possible? Is it considered a code smell or a sound design choice? I couldn't see any examples like this in the Functional Programming in Lean book, but I may well have missed it.

Kyle Miller (Sep 07 2023 at 22:54):

Yeah, I'd say that's fine. There's a bit of a tradeoff where it puts more of a proof burden inside of your algorithms, vs proving your algorithms are correct after the fact, but especially if you're not going to formally verify an algorithm, it's great being able to take advantage of Lean to embed contracts like this.

Here's something else you can do:

structure OrdPair
  lower : Nat
  higher : Nat
  is_ord : lower < higher := by simp

Then in simple cases like def p : OrdPair := {lower := 1, higher := 10} the tactic will fill in the proof automatically.

Kevin Buzzard (Sep 07 2023 at 23:09):

Surely := by norm_num?

Matthew Pocock (Sep 08 2023 at 09:31):

Kyle Miller said:

but especially if you're not going to formally verify an algorithm, it's great being able to take advantage of Lean to embed contracts like this.

At the moment these structs are there to model the domain of my proofs.

Here's something else you can do:

structure OrdPair
  lower : Nat
  higher : Nat
  is_ord : lower < higher := by simp

Oh, that's neat. Thanks :D

Matthew Pocock (Sep 08 2023 at 11:34):

Kyle Miller said:

Yeah, I'd say that's fine.

So I've written my first thing :D

def collatz (n : Nat) := if Even n then n / 2 else 3 * n + 1

structure CollatzSequence where
    left: Nat
    right: Nat
    length: Nat
    is_valid : Nat.iterate collatz length left = right

def CollatzSequence.join (ls rs : CollatzSequence) (touch: ls.right = rs.left): CollatzSequence :=
    { left := ls.left, right := rs.right , length := rs.length + ls.length, is_valid := by
        have lh := ls.is_valid
        have rh := rs.is_valid
        rw [touch] at lh
        rw [Eq.symm lh] at rh
        have cmp := Function.iterate_add_apply collatz rs.length ls.length ls.left
        simp [Eq.symm cmp] at rh
        assumption
    }

Not sure if it will be useful in practice, but it was a good learning exercise.

Eric Rodriguez (Sep 08 2023 at 11:37):

you can write Eq.symm cmp as cmp.symm by the way :) or in tactics like simp and rw, also as ←cmp.

Matthew Pocock (Sep 08 2023 at 11:55):

Ah, that certainly tidies it up a bit @Eric Rodriguez . The apply? tactic doesn't seem to know about this :/


Last updated: Dec 20 2023 at 11:08 UTC