Zulip Chat Archive

Stream: lean4

Topic: nested return in do-notation


Marcus Rossel (Sep 04 2025 at 11:31):

I think this is might be a known issue, but here's a quiz: What does Lean do in the following four examples?

def a : Id String := do
  let x  return "Lean"

def b : Id String := do
  let _  return "Lean"

def c : Id String := do
  let x  (return "Lean")

def d : Id String := do
  let x  pure "Lean"

Solution

Examples c and d feel reasonable to me, but I find a and b rather strange. Would it be possible for the linter to give an unused variable warning on a?

Marcus Rossel (Sep 04 2025 at 11:33):

For context, I ran into an example of a when looking at Grind.realizeEqProof:

private partial def realizeEqProof (lhs rhs : Expr) (h : Expr) (flipped : Bool) (heq : Bool) : GoalM Expr := do
  let h  if h == congrPlaceholderProof then
    mkCongrProof lhs rhs heq
  else
    flipProof h flipped heq

... where I was unsure if the let h ← can just be omitted.

Aaron Liu (Sep 04 2025 at 12:16):

that's a bit strance

Robin Arnez (Sep 04 2025 at 13:48):

Honestly, I don't find any of a, b, c, d particularly strange; I find

example : Id String := do
  let a  if true then pure "uhh" else pure "what"

very strange though.

Eric Wieser (Sep 06 2025 at 08:10):

def foo : Id String := do
  let a :=  if true then pure "uhh" else pure "what"

behaves correctly at least


Last updated: Dec 20 2025 at 21:32 UTC