Zulip Chat Archive

Stream: mathlib4

Topic: two errors


Heather Macbeth (Nov 07 2022 at 21:02):

I ported Logic.Function.Iterate, modulo two errors. I will make MWEs of the errors if needed, but thought I would toss the output here wholesale in case they are particular gotchas that someone will immediately recognize. One is:

fail to show termination for
  Function.RightInverse.iterate
with errors
structural recursion cannot be used

well-founded recursion cannot be used, 'Function.RightInverse.iterate' does not take any (non-fixed) arguments

and the other is

code generator does not support recursor 'Nat.rec' yet, consider using 'match ... with' and/or structural recursion

Gabriel Ebner (Nov 07 2022 at 21:52):

The second one should be self-explanatory, just avoid *.rec.

Gabriel Ebner (Nov 07 2022 at 21:52):

(This might be solved at some point in the future, but don't hold your breath.)

Gabriel Ebner (Nov 07 2022 at 21:58):

The RightInverse.iterate is a change in how name resolution works in recursive calls:

def RightInverse.iterate (h : RightInverse) : Nat :=
  h.iterate -- refers to `RightInverse.iterate`

while in Lean3 this referred to left_inverse.iterate

Heather Macbeth (Nov 13 2022 at 04:04):

In response to an error

code generator does not support recursor 'Nat.rec' yet, consider using
'match ... with' and/or structural recursion

Gabriel suggested
Gabriel Ebner said:

just avoid *.rec.

I think I can avoid using *.rec in the proof, but the name of the lemma itself is Iterate.rec. (See the mathport version). So should the lemma itself be deleted?

Mario Carneiro (Nov 13 2022 at 04:14):

Another option if the compiler gives you trouble is to mark the lemma as noncomputable

Mario Carneiro (Nov 13 2022 at 04:16):

The fact that the lemma is named *.rec doesn't matter that much. The issue is only that built-in recursors are not code-genned properly

Heather Macbeth (Nov 13 2022 at 04:20):

Mario Carneiro said:

Another option if the compiler gives you trouble is to mark the lemma as noncomputable

Thanks, this works!

Mario Carneiro (Nov 13 2022 at 04:22):

If you can make it computable, by writing it as a recursive function instead, that is preferable since it will keep downstream things computable

Heather Macbeth (Nov 13 2022 at 04:34):

I don't know how to do that (my intuition for computability is poor), but anyone should feel free to push to the branch: it's mathlib4#585 and the declaration is Iterate.rec.

Yuyang Zhao (Jan 08 2023 at 10:13):

How about implementing .rec manually for some important types before built-in recursors are supported?

Yuyang Zhao (Jan 08 2023 at 10:15):

Also to_additive does not seem to support match ... with. It complains code generator does not support recursor '*.brecOn' ....

Yuyang Zhao (Jan 08 2023 at 14:06):

Yuyang Zhao said:

How about implementing .rec manually for some important types before built-in recursors are supported?

Like this

namespace List

def rec' {C : List α  Sort _} (nil : C [])
    (cons : (head : α)  (tail : List α)  C tail  C (head :: tail)) (l : List α) : C l :=
  match l with
  | [] => nil
  | hd::tl => cons hd tl (rec' nil cons tl)

end List

Eric Wieser (Jan 08 2023 at 16:12):

Gabriel Ebner said:

(This might be solved at some point in the future, but don't hold your breath.)

Would it be easier to implement this in core than it is to change every use of rec to a match in the port?

Floris van Doorn (Jan 08 2023 at 17:28):

Yuyang Zhao said:

Also to_additive does not seem to support match ... with. It complains code generator does not support recursor '*.brecOn' ....

Oh, that is a bug, and I'm not sure how easy it is to fix. As a workaround, explicitly write down the addivite definition as well (and then additivize the multiplicative one) (and include a porting note, mentioning the tracking issue I created: mathlib4#1428).

Rémi Bottinelli (Mar 02 2023 at 11:42):

I'm having trouble understanding the code generator does not support recursor … problem:

  • The way I thought I understood things, is that the recursor is what any inductive construction compiles down to, eventually: pattern matching uses brec or well-founded recursion, which in turn is defined in terms of a recursor, which is just the induction principle of the type.
  • I also thought I understood that if you want to compile some code to something that you can run, it makes sense (for performance and probably simplicity of the generated assembler/bytecode) to instead drop the recursor and have "unchecked" recursive calls, which you know will behave well because the type is right.

So, since lean4 is also meant to be used as a programming language and be efficient at it, I would guess the compiler checks that the code is correct by way of my first bullet, and makes it compute by way of the second, but "it should be trivial" to also translate calls of rec to dumb "unchecked" recursive calls, no?

Jannis Limperg (Mar 02 2023 at 11:57):

Conceptually it's trivial, yes. The devs have indicated that they won't do it in the near future because they don't need it, but they would take a PR (though there seems to be a PR freeze atm, so this is probably not a good time).

Eric Wieser (Mar 02 2023 at 12:46):

Note that you can manually implement compiler support for the missing recursors; we do this for docs4#List.recC and docs4#Nat.recC

Rémi Bottinelli (Mar 02 2023 at 13:02):

is csimp some kind of a compiler hint?

Rémi Bottinelli (Mar 02 2023 at 13:05):

Actually, I'm still a bit confused:

  • How does the lean kernel/elaborator ensure that a definition by pattern matching is well-defined? Is the kernel still .rec all the way down?
  • As far as I understand, defining stuff without explicitly using .rec can sometimes lead to bad defeqs. How does it work around this?
    Ah, I guess having nice defeqs is solely a typechecking problem, which you don't care when compiling?

Eric Wieser (Mar 02 2023 at 13:11):

Do you have a specific rec in mind?

Eric Wieser (Mar 02 2023 at 13:12):

Yes, csimp says "use this lemma to exchange a computation-unfriendly function with nice defeqs with this efficient / computable one"

Rémi Bottinelli (Mar 02 2023 at 13:13):

Eric Wieser said:

Do you have a specific rec in mind?

Relative to my "claim" that not using rec can lead to bad defeqs? Well, I experienced a few such instances.

Eric Wieser (Mar 02 2023 at 13:14):

No, I mean a case where the Lean3 code used rec, and during porting you were coerced into using something else?

Eric Wieser (Mar 02 2023 at 13:14):

Jannis Limperg said:

Conceptually it's trivial, yes. The devs have indicated that they won't do it in the near future because they don't need it, but they would take a PR (though there seems to be a PR freeze atm, so this is probably not a good time).

Note that lean4#2049 tracks the missing compiler support for rec

Rémi Bottinelli (Mar 02 2023 at 13:15):

ah, yes, that's a problem I had with PathCategory (see thread).

Rémi Bottinelli (Mar 02 2023 at 13:15):

I just added noncomputable

Eric Wieser (Mar 02 2023 at 13:15):

You could instead define Quiver.Path.recC


Last updated: Dec 20 2023 at 11:08 UTC