Zulip Chat Archive
Stream: new members
Topic: recursive let in
Anatole Dedecker (Sep 09 2020 at 11:51):
Programming question here. Is there some way to define a recursive function using a let ... in
expression ? Here's an example in Haskell, which I don't manage to translate to Lean :
fac n =
let
aux 0 acc = acc
aux n acc = aux (n-1) (n*acc)
in
aux n 1
Reid Barton (Sep 09 2020 at 12:02):
No, I think you have to float aux
out to a top-level function if you want to use the equation compiler. Alternatively you could use the recursor directly (either in term mode or in tactic mode).
Anatole Dedecker (Sep 09 2020 at 12:03):
Ok, thanks !
Anatole Dedecker (Sep 09 2020 at 12:09):
Actually, we can even use tactic mode :sweat_smile:
def fac (n : ℕ) :=
let aux : ℕ → ℕ → ℕ :=
begin
intros k,
induction k with k hk,
{ exact id },
{ intros acc,
exact hk ((k+1) * acc) }
end
in aux n 1
Kevin Buzzard (Sep 09 2020 at 12:12):
can you prove anything about it though?
Kevin Buzzard (Sep 09 2020 at 12:12):
I am a bit scared about the proof term which induction
gives you...
Anatole Dedecker (Sep 09 2020 at 12:13):
It looks okay actually. And at least it evaluates correctly
Reid Barton (Sep 09 2020 at 12:14):
If you want to prove things about it then it's probably better to float it to top-level
Anatole Dedecker (Sep 09 2020 at 12:14):
Indeed !
Kevin Buzzard (Sep 09 2020 at 12:14):
can you prove (n+1)!=(n+1)*n! using your definition?
Anatole Dedecker (Sep 09 2020 at 13:09):
Oh that's quite annoying indeed...
Chris Wong (Sep 10 2020 at 12:20):
Is hk
just the identity function here? Trying to wrap my head around what that induction
is doing...
Eric Wieser (Sep 10 2020 at 13:56):
@Kevin Buzzard, I was able to prove it with
lemma rec_succ {C: ℕ → Type} {zero_f : C 0} {succ_f : Π n, C n → C n.succ} (n : ℕ) :
@nat.rec C zero_f succ_f (n + 1) = succ_f n (@nat.rec C zero_f succ_f n) := rfl
example (n : ℕ) : fac (n + 1) = (n+1)*(fac n) := begin
dsimp only [fac],
conv_lhs {
rw (rec_succ n),
rw mul_one,
},
generalize : n + 1 = m,
induction n with n' generalizing m,
{ simp, },
{
conv_lhs { rw n_ih},
conv_rhs { rw n_ih},
ring,
}
end
Although I feel like rec_succ
should be builtin somewhere
Eric Wieser (Sep 10 2020 at 14:24):
Ah, dsimp can handle it after a nat.add_one
:
example (n : ℕ) : fac (n + 1) = (n+1)*(fac n) := begin
rw nat.add_one n,
dsimp only [fac],
rw [mul_one, nat.add_one n],
generalize : n.succ = m,
induction n with n' generalizing m,
{ simp, },
{ conv_lhs { rw n_ih }, conv_rhs { rw n_ih }, ring, }
end
Last updated: Dec 20 2023 at 11:08 UTC