Skip to content

Instantly share code, notes, and snippets.

@ahoy-jon
Created August 21, 2025 20:43
Show Gist options
  • Save ahoy-jon/7d24ad00ea61fa13c5c4b85ceb5e1f55 to your computer and use it in GitHub Desktop.
Save ahoy-jon/7d24ad00ea61fa13c5c4b85ceb5e1f55 to your computer and use it in GitHub Desktop.
package cats
import cats.Ask.WithS
import kyo.*
import kyo.TypeMap
import kyo.kernel.ContextEffect
sealed trait Ask[R[_[_]]] extends ContextEffect[TypeMap[R[Ask.AnyS]]]
object Ask:
private trait AnyT[AnyF[_]]
private def erasedTag[R[_[_]]] = Tag[Ask[AnyT]].asInstanceOf[Tag[Ask[R]]]
type WithS[-S] = [A] =>> A < S
type Fix[R[_[_]]] = R[WithS[Ask[R]]]
private[cats] type AnyS = WithS[Any]
def use[R[_[_]]](using frame: Frame)[A, S](f: Fix[R] => A < S)(using tag: Tag[R[AnyS]]): A < (Ask[R] & S) =
ContextEffect.suspendWith(erasedTag[R]): map =>
f(map.asInstanceOf[TypeMap[R[AnyS]]].get(using tag).asInstanceOf[Fix[R]])
def get[R[_[_]]](using frame: Frame, tag: Tag[R[AnyS]]): Fix[R] < Ask[R] = use[R](identity)
def run[R[_[_]], S1](r: R[WithS[S1]])[A, S2](a: A < (Ask[R] & S2))(using tag: Tag[R[AnyS]], frame: Frame): A < (S1 & S2) =
val env: TypeMap[R[AnyS]] = TypeMap(r.asInstanceOf)
ContextEffect.handle(erasedTag[R], env, _.union(env))(a)
trait Console[F[_]]:
def read: F[String]
def printLine(line: String): F[Unit]
trait Logger[F[_]]:
def log(level: String)(message: String): F[Unit]
val comp: String < (Ask[Console] & Ask[Logger] & Sync) =
for
console <- Ask.get[Console]
logger <- Ask.get[Logger]
_ <- logger.log("Debug")("Start teletype example")
_ <- kyo.Console.printLine("Hello from Kyo")
_ <- console.printLine("Hello, World!")
_ <- console.printLine("What is your name?")
name <- console.read
_ <- console.printLine(s"Hello $name!")
yield name
val soutConsole: Console[Ask.WithS[Sync]] = new Console[WithS[Sync]]:
override def read: String < Sync = kyo.Console.readLine.orPanic
override def printLine(line: String): Unit < Sync = kyo.Console.printLine(line)
val soutLogger: Logger[Ask.WithS[Sync]] = new Logger[WithS[Sync]]:
override def log(level: String)(message: String): Unit < Sync = kyo.Console.printLine(s"[$level]: $message")
object App extends KyoApp:
comp.handle(
Ask.run(soutLogger),
Ask.run(soutConsole),
run
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment