Tracy is compatible with Kotlin from version 2.0.0 and Java from version 17. Integrations can be made with SDKs from OpenAI, Anthropic, and Gemini. The library also works with common Kotlin/LLM stacks including OkHttp and Ktor clients, as well as OpenAI, Anthropic, and Gemini ones.
When you assign the any type to a variable, you're essentially telling the compiler: Stop checking this. I'll handle it myself. At that moment, you've basically turned off TypeScript. Even worse, any tends to spread through a codebase. If a function returns any, every variable that receives that value becomes untyped as well.
Companies hiring developers with several years of experience expect candidates to demonstrate practical reasoning about functional programming patterns, concurrency models, and the Scala type system. A mid-level engineer is usually expected to work independently, contribute to design decisions, and understand the trade-offs behind the tools they use.
A real Tetris loop has time (ticks), concurrent inputs (keystrokes), state transitions (collision, locking, line clears), and non-determinism (piece generation). In many imperative designs, these concerns end up tangled in shared mutable state, which tends to produce bugs that are: hard to reproduce (timing-dependent), hard to test (logic mixed with effects), hard to debug (replay isn't deterministic).
This stands in contrast to bifunctor or polyfunctor techniques, which add a typed error channel within the monad itself. You can see this easily in type signatures: IO[String] indicates an IO which returns a String or may produce a Throwable error ( Future[String] is directly analogous). Something like BIO[ParseError, String] would represent a BIO that produces a String or raises a ParseError.