Zulip Chat Archive

Stream: lean4

Topic: Converting a simple function from Lean3 to Lean4


Richard Evans (Apr 15 2022 at 14:11):

Apologies in advance: this is a beginner's question as well as a Lean4 question.

I am trying to convert a simple function from Lean3 to Lean4.

Here is the original Lean3 function (from https://github.com/blanchette/logical_verification_2020/tree/master/lean)

def drop {α : Type} :   list α  list α
| 0       xs        := xs
| (_ + 1) []        := []
| (m + 1) (x :: xs) := drop m xs

To convert to Lean4, I replaced list with List and also added an explicit match (because Lean4 doesn't seem to like | on multiple arguments unless I am missing something):

def drop {α : Type} : Nat  List α  List α := λ n as => match (n, as) with
| (0,       xs)         => xs
| (_ + 1,   [])         => []
| (Nat.succ m, x :: xs) => drop m xs

But Lean4 doesn't like this because it cannot prove that it terminates:

fail to show termination for drop with errors: argument #2 was not used for structural recursion failed to eliminate recursive application drop m xs

Can someone please explain what is going on? Thanks in advance.

Henrik Böving (Apr 15 2022 at 14:13):

So first things first you can actually write it like this:

def drop {α : Type} : Nat  List α  List α
| 0,       xs        => xs
| (_ + 1), []        => []
| (m + 1), (x :: xs) => drop m xs

secondly, the termination checker does solve this just fine for me.

Sébastien Michelland (Apr 15 2022 at 14:14):

You're not matching on the second argument but on a pair built using the second argument, which "hides" the structural recursion. If you match on the two values rather than a pair, it works:

def drop {α : Type} : Nat  List α  List α := λ n as => match n, as with
| 0,       xs         => xs
| _ + 1,   []         => []
| Nat.succ m, x :: xs => drop m xs

You can also drop the match, as Henrik just showed.

Richard Evans (Apr 15 2022 at 14:15):

That's great. Thank you!


Last updated: Dec 20 2023 at 11:08 UTC