Skip to content
Oeiuwq Faith Blog OpenSource Porfolio

marcinzh/turbolift

Algebraic Effects for Scala 3

marcinzh/turbolift.json
{
"createdAt": "2019-04-14T18:00:05Z",
"defaultBranch": "master",
"description": "Algebraic Effects for Scala 3",
"fullName": "marcinzh/turbolift",
"homepage": "https://marcinzh.github.io/turbolift/",
"language": "Scala",
"name": "turbolift",
"pushedAt": "2025-10-10T11:48:48Z",
"stargazersCount": 79,
"topics": [
"algebraic-effects",
"functional-programming",
"scala"
],
"updatedAt": "2025-11-17T16:06:16Z",
"url": "https://github.com/marcinzh/turbolift"
}

Maven Central Version javadoc

Visit the microsite for description.

See also:

ProjectDescription
DaaEDemo: a debugger implemented as an effect
SpotCats-Effect instances for Turbolift’s IO effect
EnterpriseHTTP server implemented using Turbolift’s effects
BeamStreams implemented with Turbolift’s effects
Effect ZooMicrobenchmark suite for several effect systems, including Turbolift

Runnable with scala-cli.

[!IMPORTANT] Turbolift requires Java 11 or newer.

//> using scala "3.3.6"
//> using dep "io.github.marcinzh::turbolift-core:0.122.0"
import turbolift.!!
import turbolift.effects.{Reader, State, Error}
@main def main =
val program =
for
a <- State.get[Int]
b <- Reader.ask[Int]
c <-
if b != 0
then !!.pure(a / b)
else Error.raise(s"Tried to divide $a by zero")
_ <- State.put(c)
yield ()
val result =
program
.handleWith(State.handler(100))
.handleWith(Reader.handler(3))
.handleWith(Error.handler)
.run
println(result) // Right(((),33))

 

Same, but with [bindless]!(modules/bindless) syntax extension (async/await alike):

//> using scala "3.3.6"
//> using dep "io.github.marcinzh::turbolift-core:0.122.0"
//> using dep "io.github.marcinzh::turbolift-bindless:0.122.0"
import turbolift.!!
import turbolift.effects.{Reader, State, Error}
import turbolift.bindless._
@main def main =
val program =
`do`:
val a = State.get[Int].!
val b = Reader.ask[Int].!
val c =
if b != 0
then a / b
else Error.raise(s"Tried to divide $a by zero").!
State.put(c).!
val result =
program
.handleWith(State.handler(100))
.handleWith(Reader.handler(3))
.handleWith(Error.handler)
.run
println(result) // Right(((),33))

 

Same as the first example, but using monomorphized effect instances:

  • 👍 Better for modularity (see Labeled Effects).
  • 👍 QOL: Helps type inference and improves clarity of error messages.
  • 👎 Slightly more verbose, since effect instance definitions are required (e.g. case object MyEffect extends SomeEffect).
//> using scala "3.3.6"
//> using dep "io.github.marcinzh::turbolift-core:0.122.0"
import turbolift.!!
import turbolift.effects.{ReaderEffect, StateEffect, ErrorEffect}
@main def main =
// 👉 Definitions of custom effect instances:
case object MyReader extends ReaderEffect[Int]
case object MyState extends StateEffect[Int]
case object MyError extends ErrorEffect[String]
val program =
for
a <- MyState.get // 👉 No need for explicit type parameter: `get[Int]`
b <- MyReader.ask // 👉 No need for explicit type parameter: `ask[Int]`
c <-
if b != 0
then !!.pure(a / b)
else MyError.raise(s"Tried to divide $a by zero")
_ <- MyState.put(c)
yield ()
val result =
program
.handleWith(MyState.handler(100))
.handleWith(MyReader.handler(3))
.handleWith(MyError.handler)
.run
println(result) // Right(((),33))

 

See also [examples]!(modules/examples/src/main/scala/examples/) folder. Runnable with sbt:

Terminal window
sbt examples/run
libraryDependencies += "io.github.marcinzh" %% "turbolift-core" % "0.122.0"

Optionally, for the [bindless]!(modules/bindless) syntax extension:

libraryDependencies += "io.github.marcinzh" %% "turbolift-bindless" % "0.122.0"