Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More convenient direct syntax #713

Closed
fwbrasil opened this issue Oct 2, 2024 · 4 comments
Closed

More convenient direct syntax #713

fwbrasil opened this issue Oct 2, 2024 · 4 comments

Comments

@fwbrasil
Copy link
Collaborator

fwbrasil commented Oct 2, 2024

I've been considering ways to make the direct syntax more convenient but with a smaller scope than #211. The integration with dotty-cps-async is working well but it'd be nice if we had a way to avoid the need for await calls. Currently, code using the direct syntax looks like this:

import kyo.*

val a: String < IO =
    defer {
        val a: String = await(IO("hello"))
        val b: String = await(IO("world"))
        a + " " + b
    }

To avoid the need for await, we could have wrappers of Kyo's regular APIs using transparent inline to automatically insert the necessary awaits. Each API would have a counterpart in a kyo.direct package. Example for IO:

package kyo.direct

// Interop with the regular monadic APIs via a type bound
opaque type IO <: kyo.IO = kyo.IO

object IO:
    transparent inline def apply[A, S](inline f: => A)(using Frame): A = await(kyo.IO(f))

Users would then import kyo.direct.* instead of import kyo.*, which wouldn't require explicit awaits:

import kyo.direct.*

val a: String < IO =
    defer {
        val a: String = IO("hello")
        val b: String = IO("world")
        a + " " + b
    }

We might hit limitations but my initial tests indicate it's a viable approach.

If we decide to proceed, I think we could merge kyo-direct into kyo-prelude so the direct wrappers stay in the same module as their monadic APIs. Another option is having separate modules like kyo-prelude-direct and kyo-core-direct but I think it'd make maintenance harder and we might end up with too many modules.

cc/ @rssh

@fwbrasil
Copy link
Collaborator Author

fwbrasil commented Oct 2, 2024

I've prepared a prototype to explore the idea: https://gist.github.com/fwbrasil/bc8e27aeaf7c0c992b0d103638a71b90

It's possible to execute it with:

scala-cli https://gist.github.com/fwbrasil/bc8e27aeaf7c0c992b0d103638a71b90

@rssh
Copy link

rssh commented Oct 3, 2024

It is possible to call. IO("hello") outside defer brackets?
If not - it means that we will have two completely different API for sync and async part.

@fwbrasil
Copy link
Collaborator Author

fwbrasil commented Oct 3, 2024

If not - it means that we will have two completely different API for sync and async part.

Yes, the idea is to have wrapper APIs via transparent inline in a different package. In Kyo's context, it's not about sync/async but efffectful/non-effectful since the pending type can express an unbounded number of effects, not only async.

@fwbrasil
Copy link
Collaborator Author

fwbrasil commented Dec 4, 2024

The mix of code that requires await with code that doesn't require await is too confusing. Closing.

@fwbrasil fwbrasil closed this as completed Dec 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants