Zulip Chat Archive
Stream: new members
Topic: Using If-Statement Test to Cast or Rewrite value
Greg B (Mar 07 2025 at 22:42):
I am trying to figure out how I can use the truth value of an If-Statement to inform the Lean type-checker that I have a particular type or rewrite the value. The primary goal is to avoid recomputing the conditions tested by the predicate in the If-Statement.
Here is an example of testing to determine which part of a Sum type is being used and then rewriting it to eliminate the Sum type. I feel I shouldn't have to pattern match to de-structure selector
since that has already been done by the predicate hasBar
. Is this something that can be done in Lean4? I know I can refactor this to make pattern matching more convenient, but I am not sure if there is another technique.
inductive Foo where
| foo
inductive Bar where
| baz
inductive Selector (α : Type) where
| Input (values: α)
| Constant
def getInput {α : Type} : Selector α → Option α := fun
| Selector.Input values => some values
| _ => none
def get_or_else {α : Type} (o: Option α) (default : α): α := match o with
| some value => value
| none => default
def hasBar (selector : Selector (Sum Foo Bar)) : Bool := getInput selector |> (Option.map Sum.isRight) |> (get_or_else · false)
theorem has_bar_is_bar (selector : Selector (Sum Foo Bar)) : hasBar selector = true → selector = Selector.Input (Sum.inr Bar.baz) := sorry
def test (selector : Selector (Sum Foo Bar)) : Selector Bar :=
if h : hasBar selector then
have g : selector = Selector.Input (Sum.inr Bar.baz) := has_bar_is_bar selector h
Selector.Input selector.values -- What can I put here to cast the value based on the proof g?
else
Selector.Input Bar.baz
I am not too sure of the right vocabulary to use when asking this question, so I can try to clarify anything if needed. Thank you for any help and your understanding.
Aaron Liu (Mar 07 2025 at 23:08):
Can you post a #mwe?
Greg B (Mar 07 2025 at 23:37):
Whoops sorry, yes. I missed that one definition.
Chris Bailey (Mar 07 2025 at 23:58):
Can you describe exactly what the desired effect is? Are you wanting to cast a Selector (Foo ⊕ Bar)
as a Selector Bar
using h & g?
Chris Bailey (Mar 07 2025 at 23:58):
Oh the code example completely changed.
Greg B (Mar 08 2025 at 00:00):
I was trying to work it down to a mwe.
Greg B (Mar 08 2025 at 00:00):
I will put the original back and then post another mwe
Greg B (Mar 08 2025 at 00:01):
variable {Foo : Type}
inductive Bar where
| bar
def hasBar : (Sum Foo Bar) → Bool := Sum.isRight
theorem has_bar_is_bar (selector : Sum Foo Bar) : hasBar selector = true → selector = Sum.inr Bar.bar := sorry
def test (selector : Sum Foo Bar) : Bar :=
if h : hasBar selector then
have g : selector = (Sum.inr Bar.bar) := has_bar_is_bar selector h
sorry -- What can I put here to cast the value based on the proof g?
else
Bar.bar
Greg B (Mar 08 2025 at 00:05):
Yes. That is the desired effect. Cast Selector (Foo ⊕ Bar)
as a Selector Bar
using h & g. Or something similar.
Chris Bailey (Mar 08 2025 at 00:06):
Since you're already aware you can just move the pattern match to the outside, I think this is the most minimal way to do it keeping everything in the same position. You're still nominally repeating the pattern match by calling getRight
, but I don't know whether the compiler does any optimizations for pattern matches with a single arm:
def test (selector : Sum Foo Bar) : Bar :=
if h : hasBar selector then
have g : selector = (Sum.inr Bar.bar) := has_bar_is_bar selector h
selector.getRight (by simp only [g, Sum.isRight_inr])
else
Bar.bar
Greg B (Mar 08 2025 at 00:23):
Ah! I think I understand now. Thank you! That is a big help!
Chris Bailey (Mar 08 2025 at 00:31):
Yeah sorry it's basically passing the evidence from g
to Sum.getRight
which is provided for you, and that definition is (sort of implicitly) using the provided evidence to reduce the match to one with a single arm; the pattern match in getRight
knows that the other case is not required.
def getRight : (ab : α ⊕ β) → ab.isRight → β
| inr b, _ => b
Last updated: May 02 2025 at 03:31 UTC