Zulip Chat Archive
Stream: lean4
Topic: Stack safe Bind
Juan Pablo Romero (Jul 17 2022 at 16:51):
Is it possible to build a stack safe Bind/Monad (a la IO) purely within Lean? or does it require special runtime support?
For example I'd like to write a stack safe function like this:
instance : Monad M where
pure := ...
bind := ...
def repeatN (ma: M A) (n: Nat) : M Unit := do
let _ <- ma
if n > 0 then
repeatN ma (n - 1)
Henrik Böving (Jul 17 2022 at 17:05):
What do you mean by stack safe? That it doesn't kill the program in case it overflows?
Juan Pablo Romero (Jul 17 2022 at 17:07):
Yeah, I'm trying to avoid stack overflows, basically
Henrik Böving (Jul 17 2022 at 17:08):
I'd say since it depends highly on compiler optimizations if and how much stack space is used this seems quite impossible to do precisely?
Kyle Miller (Jul 17 2022 at 17:09):
I think the question here is about whether Lean does tail call optimization for monadic functions
Juan Pablo Romero (Jul 17 2022 at 17:09):
right
Chris Bailey (Jul 17 2022 at 17:10):
The CPS monads in Init.Control do (or did). You might also be able to use the loop syntax.
Juan Pablo Romero (Jul 17 2022 at 17:12):
oh, let me take a look
Sebastian Ullrich (Jul 17 2022 at 17:16):
I'd say this should just work iff your bind
calls the second argument in tail position
Juan Pablo Romero (Jul 17 2022 at 17:26):
got it. In this case M is a GADT which only captures its arguments:
inductive M : Type -> Type 1 where
...
| Bind (ma: M A) (f: A -> M B) : M B
and later gets interpreted
def run (m: M A) (callback: A -> IO Unit) : IO Unit := match m with
...
| .Bind ma cont =>
run ma $ fun a => run (cont a) callback
...
I guess this is where the Stack Overflow is coming.
Last updated: Dec 20 2023 at 11:08 UTC