Zulip Chat Archive
Stream: new members
Topic: mutual recursion -help (fmany - fsome)
lorã (Jun 07 2025 at 12:52):
For this code
mutual
def fmany [Alternative f] (x : f α) : f (List α) := fsome x <|> pure []
def fsome [Alternative f] (x : f α) : f (List α) := pure (· :: ·) <*> x <*> fmany x
termination_by structural {
sorry
}
end
I got this output
typeclass instance problem is stuck, it is often due to metavariables
EmptyCollection ?m.13593
Thats only the second time that im trying to solve a mutual recursion problem, but this one is harder than the another. Can i ask for some help?
Aaron Liu (Jun 07 2025 at 13:10):
What is you argument that this pair of functions is terminating?
lorã (Jun 07 2025 at 15:39):
What is you argument that this pair of functions is terminating?
Sorry, i dont think i get it
lorã (Jun 07 2025 at 15:55):
this is a standard implementation in haskell, so I thought it should work
Aaron Liu (Jun 07 2025 at 17:03):
You need to make sure your implementation doesn't go into an infinite loop.
lorã (Jun 07 2025 at 17:19):
How can i fight with the lean system to prove that? Even the goal's not making a lot of sense to me. I tried to use the key word partial but also didnt work
Aaron Liu (Jun 07 2025 at 17:35):
section
instance [i : Nonempty α] [Pure f] : Nonempty (f α) :=
i.elim fun a => ⟨pure a⟩
mutual
partial def fmany [Alternative f] (x : f α) : f (List α) := fsome x <|> pure []
partial def fsome [Alternative f] (x : f α) : f (List α) := pure (· :: ·) <*> x <*> fmany x
end
end
Aaron Liu (Jun 07 2025 at 17:35):
Though with partial you can't prove anything about the definitions
Aaron Liu (Jun 07 2025 at 17:37):
If you prove you definitions will never generate an infinite loop you don't have to use partial
Aaron Liu (Jun 07 2025 at 17:39):
Do note that every list in Lean is provably finite
Aaron Liu (Jun 07 2025 at 17:39):
Lean is also a strict language, unlike Haskell which is lazy.
Mario Carneiro (Jun 07 2025 at 18:13):
Here's a proof that this pair of functions can't be proved to terminate because the equations are inconsistent:
local instance [Alternative f] : Inhabited (f (List α)) := ⟨pure []⟩ in
mutual
partial def fmany [Alternative f] (x : f α) : f (List α) := fsome x <|> pure []
partial def fsome [Alternative f] (x : f α) : f (List α) := pure (· :: ·) <*> x <*> fmany x
end
axiom fmany_eq [Alternative f] (x : f α) : fmany x = (fsome x <|> pure [])
axiom fsome_eq [Alternative f] (x : f α) : fsome x = (pure (· :: ·) <*> x <*> fmany x)
structure Foo (_ : Type) where
depth : Nat
instance : Alternative Foo where
pure _ := ⟨0⟩
seq _ b := ⟨(b ()).depth⟩
failure := ⟨0⟩
orElse a _ := ⟨a.depth + 1⟩
example : False := by
suffices ∀ n (x : Foo Nat), (fmany x).depth = n → False from this _ ⟨0⟩ rfl
intro n x eq
induction n generalizing x with
simp [fmany_eq, (· <|> ·), OrElse.orElse, Alternative.orElse] at eq
| succ n ih =>
simp [fsome_eq, Seq.seq] at eq
exact ih _ eq
Last updated: Dec 20 2025 at 21:32 UTC