Skip to content
/ task Public

Task -- A lightweight, error-typed monad for Scala built atop scala.concurrent.Future with zero dependencies

License

Ragazoor/task

Repository files navigation

Scala Steward badge CI Badge Maven Central Version

The future of scala.concurrent.Future

logo.png A Future based monad with a typed error channel, made for domain driven asynchronous programming in Scala.


⚠️ Note: This is a side project I made for fun, not a production grade library.

🧰 Why this library?

Task[E, A] is a lightweight monad built on top of scala.concurrent.Future, but with a type parameter for the error channel. The advantage of this is that if a function return a Task[DomainException, Int] it can only fail with an error which is a subtype of DomainException (or a fatal exception).

Task can also be used interchangeably with the Future monad and has the same performance. This means that you do not need to learn or introduce a new effect system to your codebase and your code can use the same libraries that you are already using with Future. Finally, this library is designed to be as lightweight as possible, and has no dependencies. Since it's so small you can also copy it to your own project to test it.

Similar Libraries

If you are already used to working with typed errors and instead want to go the extra mile to change effect system I would recommend checking out ZIO or Monix BIO.

⚙️ Getting Started

Installation

Setup via build.sbt:

libraryDependencies += "io.github.ragazoor" %% "task" % "0.1.18"

Examples

  • Basic usage link:
    • Code with error types
    • Conversion from Future to Task
    • Mapping errors Throwable to custom error type
  • Interoperability with scala.concurrent.Future libraries link:
  • Migrating from scala.concurrent.Future to Task link:

📋 Migration

The goal of this library is to be as lightweight as possible, with this in mind I am reusing as much as possible from scala.concurrent._. This makes migration easy as well, it is mostly about replacing scala.concurrent.Future with io.github.ragazoor.task._ and io.github.ragazoor.task.implicits._.

You have to fix the code manually mainly in the following ways:

  • If we are using a third-party library returning a scala.concurrent.Future we need to convert it to Task using .toTask and the implicit class in io.github.ragazoor.task.implicits.FutureToTask.
  • If we are using implicit classes which act on scala.concurrent.Future, fix the implicit class or convert task to Future using .toFuture
  • If you have interfaces in your code like A => StdFuture[B], which are hard to change, there are implicits in import io.github.ragazoor.task.migration.implicits._ to help.
  • If you are using implicit classes that extends scala.concurrent.Future the compiler will not be able to convert like one might think using the migration implicits. So we need to make it explicit:

🚀 Benchmarks

Run benchmarks with

sbt "benchmark/jmh:run -i 10 -wi 10 -f 1 -t 1 io.github.ragazoor.task.TaskBenchmark"
[info] Benchmark                      Mode  Cnt   Score   Error  Units
[info] TaskBenchmark.futureFlatMap   thrpt   10  34.419 ± 1.406  ops/s
[info] TaskBenchmark.futureMap       thrpt   10  34.556 ± 0.850  ops/s
[info] TaskBenchmark.futureRecover   thrpt   10  33.102 ± 0.802  ops/s
[info] TaskBenchmark.futureSequence  thrpt   10   1.858 ± 0.019  ops/s
[info] TaskBenchmark.taskFlatMap     thrpt   10  34.451 ± 0.961  ops/s
[info] TaskBenchmark.taskMap         thrpt   10  36.490 ± 1.042  ops/s
[info] TaskBenchmark.taskMapError    thrpt   10  35.284 ± 1.302  ops/s
[info] TaskBenchmark.taskSequence    thrpt   10   1.558 ± 0.047  ops/s

About

Task -- A lightweight, error-typed monad for Scala built atop scala.concurrent.Future with zero dependencies

Topics

Resources

License

Stars

Watchers

Forks

Contributors 3

  •  
  •  
  •  

Languages