Zulip Chat Archive

Stream: lean4

Topic: if-else block that isn't `m Unit` can discard result


Jovan Gerbscheid (Feb 24 2025 at 17:21):

Is it expected that this doesn't throw an error?

def foo {α : Type} (a b c : α) : Id α := do
  if true then
    pure a
  else
    pure b
  pure c

#eval foo 1 2 3 -- 3

Arthur Paulino (Feb 24 2025 at 20:36):

Yeah this looks odd. But I think it's doing this:

def foo {α : Type} (a b c : α) : Id α := do
  let _ <- if true then
      pure a
    else
      pure b
  pure c

Which is sensible

Edward van de Meent (Feb 24 2025 at 20:37):

the odd(?) thing is that it doesn't do that when you drop the pure c line

Mario Carneiro (Feb 24 2025 at 21:18):

I think you should view this as similar to

example : Id Nat := do
  pure 1
  pure 2

Mario Carneiro (Feb 24 2025 at 21:20):

oh, actually that's a bad example, that works only with import Mathlib because 1 is interpreted as living in PUnit because it's a ring :face_with_peeking_eye:

Mario Carneiro (Feb 24 2025 at 21:22):

So I'm on the side "this is not sensible", the let _ <- part is deliberately omitted when you just have a sequence of do elems (in fact it is more like let () <-)

Mario Carneiro (Feb 24 2025 at 21:23):

to make the distinction a little more stark:

example : Id Nat := do
  if true then pure 1 else pure 2 -- ok
  pure 3

example : Id Nat := do
  (if true then pure 1 else pure 2) -- fail
  pure 3

Kim Morrison (Feb 24 2025 at 21:41):

Perhaps PUnit should not itself be a ring, and Mathlib could make an alternative equivalent type to carry this structure!

Edward van de Meent (Feb 24 2025 at 21:48):

Mario Carneiro said:

I think you should view this as similar to

example : Id Nat := do
  pure 1
  pure 2

Indeed, I was hoping that throwing away the result would be the default behaviour in do notation, just like in Haskell, but since that isn't the case, it's odd that if does have this behaviour

Mario Carneiro (Feb 24 2025 at 21:54):

it used to discard, this behavior was changed I think because it makes it easier to spot bugs where return values are silently discarded. You should use let _ <- to explicitly drop a value you don't want

Mario Carneiro (Feb 24 2025 at 21:55):

or _ <- if you are feeling pressed for characters


Last updated: May 02 2025 at 03:31 UTC