Skip to content

Conversation

@johnynek
Copy link
Contributor

It took me a bit of thinking to implement this, so I think it could be of use. This simplifies writing a recursive function over a Defer[F] instance. This is particularly useful with monad transformers that give you Defer instances, e.g. EitherT[IO, MyError, A]

*/
def recursiveFn[A, B](fn: (A => F[B]) => (A => F[B])): A => F[B] =
new Function1[A, F[B]] { self =>
lazy val loopFn: A => F[B] = fn(self)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we make this a lazy val so it is only evaluated once but only inside the defer below so we want until the first time it is actually need.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but now that I write that down, I can't see a reason why you would need this. You should only apply self inside the recursion, but that means only when loopFn is called, which we don't do until we return the value, so it should be safe.

@satorg
Copy link
Contributor

satorg commented Sep 24, 2024

Interesting thought, thank you!
If I'm getting it correctly, recursiveFn looks like a generalization of fix in some way,
i.e. having fn: F[A] => F[A] we can probably assume that

fix(fn) <=> recursiveFn[Unit, A] { u2fa => Function.const[F[A], Unit](u2fa(())) }(())

Copy link
Contributor

@satorg satorg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks!

@johnynek
Copy link
Contributor Author

I think your law is correct, but also hard to test. Most randomly generated random functions won't terminate I think (or at least many won't). So I don't know if we can actually make that test.

@johnynek johnynek merged commit 5fc8ede into main Sep 25, 2024
33 checks passed
@satorg satorg deleted the oscar/20240922_defer_recursivefn branch July 6, 2025 02:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants