building upon #3714, this (almost) implements the second half of #3302. The main effect is that we now get a better error message when `rfl` fails. For ```lean example : n+1+m = n + (1+m) := by rfl ``` instead of the wall of text ``` The rfl tactic failed. Possible reasons: - The goal is not a reflexive relation (neither `=` nor a relation with a @[refl] lemma). - The arguments of the relation are not equal. Try using the reflexivity lemma for your relation explicitly, e.g. `exact Eq.refl _` or `exact HEq.rfl` etc. n m : Nat ⊢ n + 1 + m = n + (1 + m) ``` we now get ``` error: tactic 'rfl' failed, the left-hand side n + 1 + m is not definitionally equal to the right-hand side n + (1 + m) n m : Nat ⊢ n + 1 + m = n + (1 + m) ``` Unfortunately, because of very subtle differences in semantics (which transparency setting is used when reducing the goal and whether the “implicit lambda” feature applies) I could not make this simply the only `rfl` implementation. So `rfl` remains a macro and is still expanded to `eq_refl` (difference transparency setting) and `exact Iff.rfl` and `exact HEq.rfl` (implicit lambda) to not break existing code. This can be revised later, so this still closes: #3302. A user might still be puzzled *why* to terms are not defeq. Explaining that better (“reduced to… and reduces to… etc.”) would also be great, but that’s not specific to `rfl`, so better left for some other time.
47 lines
1.7 KiB
Text
47 lines
1.7 KiB
Text
-- NB: well-founded recursion, so irreducible
|
||
def sorted_from_var [x: LE α] [DecidableRel x.le] (a: Array α) (i: Nat): Bool :=
|
||
if h: i + 1 < a.size then
|
||
have : i < a.size := Nat.lt_of_succ_lt h
|
||
a[i] ≤ a[i+1] && sorted_from_var a (i + 1)
|
||
else
|
||
true
|
||
termination_by a.size - i
|
||
|
||
def check_sorted [x: LE α] [DecidableRel x.le] (a: Array α): Bool :=
|
||
sorted_from_var a 0
|
||
|
||
/--
|
||
error: tactic 'rfl' failed, the left-hand side
|
||
check_sorted #[0, 3, 3, 5, 8, 10, 10, 10]
|
||
is not definitionally equal to the right-hand side
|
||
true
|
||
⊢ check_sorted #[0, 3, 3, 5, 8, 10, 10, 10] = true
|
||
-/
|
||
#guard_msgs in
|
||
example: check_sorted #[0, 3, 3, 5, 8, 10, 10, 10] = true := by
|
||
rfl -- fails because `rfl` uses `.default` transparency, and `sorted_from_var` is marked as irreducible
|
||
|
||
/--
|
||
error: tactic 'decide' failed for proposition
|
||
check_sorted #[0, 3, 3, 5, 8, 10, 10, 10] = true
|
||
since its 'Decidable' instance
|
||
instDecidableEqBool (check_sorted #[0, 3, 3, 5, 8, 10, 10, 10]) true
|
||
did not reduce to 'isTrue' or 'isFalse'.
|
||
|
||
After unfolding the instances 'instDecidableEqBool' and 'Bool.decEq', reduction got stuck at the 'Decidable' instance
|
||
match check_sorted #[0, 3, 3, 5, 8, 10, 10, 10], true with
|
||
| false, false => isTrue ⋯
|
||
| false, true => isFalse ⋯
|
||
| true, false => isFalse ⋯
|
||
| true, true => isTrue ⋯
|
||
-/
|
||
#guard_msgs in
|
||
example: check_sorted #[0, 3, 3, 5, 8, 10, 10, 10] := by
|
||
decide -- fails because `decide` uses `.default` transparency, and `sorted_from_var` is marked as irreducible
|
||
|
||
unseal sorted_from_var in
|
||
example: check_sorted #[0, 3, 3, 5, 8, 10, 10, 10] := by
|
||
decide -- works
|
||
|
||
example: check_sorted #[0, 3, 3, 5, 8, 10, 10, 10] := by
|
||
with_unfolding_all decide -- should work
|