Skip to content

Design & implement TF-bridge #43

@haskiindahouse

Description

@haskiindahouse

Do YAES need something like a bridge? (btw open question)

(inspired by Kyo’s Cats / ZIOs bridges and the community PoC gist https://gist.github.com/mucaho/d80551dd0b62c59ce0e2186608482577)

Motivation

Kyo shows a proven migration path by shipping lightweight bridges (kyo-cats, kyo-zios) that lift TF programs into Kyo effects and lower them back when needed.
A recent community gist demonstrates how the same idea can work for YÆS by hand-rolling small capability wrappers and providing Monad, Raise, Stateful, etc. instances.

Giving YÆS a first-class, batteries-included TF interop module 😄 will:

  • remove the “lock-in” fear for existing Cats/ZIO codebases;
  • unlock immediate use of the vast Typelevel ecosystem (http4s, Doobie, FS2, etc.)

Scope / Deliverables

# Deliverable Details
1 yaes-interop-cats module Artifacts: "in.rcard.yaes" %% "yaes-interop-cats" % x.y.z.
• Effect Cats exposing Cats.get(io: IO[A]): A and Cats.run { … }: IO[A].
• Type-class instances: given Monad[[A] =>> Cats ?=> A], given cats.effect.Sync[[A] =>> Cats ?=> A], given cats.mtl.Raise[[A] =>> Cats ?=> A, E], etc.
2 yaes-interop-zio module Mirror of (1) but for ZIO.
Zios.get(task: Task[A]): A / Zios.run { … }: Task[A].
• Propagate cancellation & interruption semantics like zio.interop.catz
3 Capability lifting helpers Utilities to convert YaesFibercats.effect.Fiber, YaesFiberzio.Fiber, preserving cancel semantics.
4 Law-testing & Examples Discipline-based tests proving Monad/Sync laws; example that runs http4s + Doobie inside YÆS via the bridge
5 Docs & Migration Guide README for each module + cookbook: “Refactor CE program to YÆS in 3 steps”. Reference the PoC gist for deeper rationale

Non-goals (for this ticket)

  • General mtl-style or BIO/Tofu support.

API Sketch (Cats bridge)

object Cats:
  type Cats = Yaes[Cats.Unsafe]

  def get[A](io: cats.effect.IO[A])(using Cats): A =
    Cats(io)                        // lift

  def run[A](block: Cats ?=> A): cats.effect.IO[A] =
    Yaes.handle(block)(
      new Yaes.Handler[Cats.Unsafe, A, cats.effect.IO[A]]:
        def handle(p: Cats ?=> A) =
          cats.effect.IO.blocking(p(using Yaes(unsafe)))
    )

  private val unsafe: Unsafe = (io: cats.effect.IO[?]) => io.unsafeRunSync()

  trait Unsafe:
    def apply[A](io: cats.effect.IO[A]): A

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions