Skip to content

Lemmata for if_then_else_ #2747

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open

Lemmata for if_then_else_ #2747

wants to merge 9 commits into from

Conversation

pmbittner
Copy link
Contributor

We used if_then_else_ a lot in one of our projects and it turned out that sometimes these basic lemmata on if_then_else_ are quite useful. While it is typically straightforward to resolve if_then_else_ expressions by pattern matching on the boolean condition instead, sometimes it is convenient to use these lemmata when an if_then_else_ occurs somewhere deep in an equational-reasoning chain.

@@ -745,6 +745,50 @@ if-float : ∀ (f : A → B) b {x y} →
if-float _ true = refl
if-float _ false = refl

if-idemp : ∀ b {x : A} →
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normally we abbreviate idempotent to idem

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it more of an if-eta?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if-eta is a good name because it removes the unnecessary if-abstraction. Idempotence might rather be something like the following, which I am going to add:

if-idem :  b {x y : A}  (if b then (if b then x else y) else y) ≡ (if b then x else y)
if-idem false = refl
if-idem true  = refl

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah and this is again rather an if-idem-then and there is also an if-idem-else.

@@ -745,6 +745,50 @@ if-float : ∀ (f : A → B) b {x y} →
if-float _ true = refl
if-float _ false = refl

if-idemp : ∀ b {x : A} →
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it more of an if-eta?

if-idemp false = refl
if-idemp true = refl

if-swap : ∀ b c {x y : A} →
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this if-swapʳ? Which suggests there's an opportunity for a left version too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer it was called if-swap-else, there's three sides to every if (and similar for the if-congs below)

Copy link
Contributor Author

@pmbittner pmbittner Jun 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I will rename the theorem to if-swap-else, and I will also add the if-swap-then case.

Speaking of the cong-theorems, I noticed that a cong-theorem for the boolean condition is missing, so I am going to add that as well.

@pmbittner pmbittner force-pushed the if-lemmas branch 2 times, most recently from 6740db7 to 317ecfb Compare June 26, 2025 06:50
if-xor true {false} = refl
if-xor true {true } = refl

if-cong : ∀ {b c} {x y : A} → b ≡ c →
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about it, isn't this just cong (if_then x else y)? And similar for the other cong lemmas. Is it worth including?

Copy link
Contributor Author

@pmbittner pmbittner Jun 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is indeed exactly that.

The benefit of the if-cong lemmas is that we can infer some of the branches automatically with implicit arguments, so we can omit them. That was the reason why I created these cong-lemmas in our project because sometimes we had large expressions in these branches and it was tedious to spell them out. Example:

open import Data.Bool using (if_then_else_)
open import Data.Bool.Properties using (if-cong-else)
open import Data.Nat using (ℕ; _+_)
open import Data.Nat.Properties using (+-comm)
open import Relation.Binary.PropositionalEquality as Eq using (_≡_; refl; cong)

looooooong-expression = 1

with-if-cong :  b (x y : ℕ)
   (if b then looooooong-expression else x + y)
  ≡ (if b then looooooong-expression else y + x)
with-if-cong b x y = if-cong-else b (+-comm x y)

with-cong :  b (x y : ℕ)
   (if b then looooooong-expression else x + y)
  ≡ (if b then looooooong-expression else y + x)
with-cong b x y = cong (if b then looooooong-expression else_) (+-comm x y)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not help with all elements within an if_then_else_ though because we still have to spell out the condition (b in the example above).

Copy link
Contributor

@JacquesCarette JacquesCarette left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice.

A lot of these generalize to partitions and piecewise functions. Which I should implement.

@pmbittner pmbittner changed the title Lemmata for if_then_else Lemmata for if_then_else_ Jun 26, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants