An Arrow
represents a computation that can be reused by multiple executions.
An Arrow
represents a computation that can be reused by multiple executions.
It's a function that can be composed using methods similar to Future
. For example:
// regular future composition def callAService(i: Int): Future[Int] = ??? def myTransformation(i: Int): Future[Int] = callServiceA(i).map(_ + 1) val result: Future[Int] = myTransformation(1) // using arrows val callServiceA: Arrow[Int, Int] = ??? val myTransformation: Arrow[Int, Int] = callServiceA.map(_ + 1) val result: Future[Int] = myTransformation.run(1)
Note that the arrows can be created once and reused for multiple run
invocations
Arrow also has a specialization called Task
that provides an interface that allows
users to express computations that don't take inputs:
// task composition def callAService(i: Int): Task[Int] = ??? def myTransformation(i: Int): Task[Int] = callServiceA(i).map(_ + 1) val result: Future[Int] = myTransformation(1).run
It's similar to Future
compositions, but the execution is lazy. The Task
creation
only creates a computation that is executed once run
is called.
Arrow.apply
returns an identity arrow that is a convenient way to create arrows:
val myArrow: Arrow[Int, Int] = Arrow[Int].map(_ + 1)
arrow.apply
can be used to produce Task
s. It's useful to express computations that vary
their structure based on input values:
val someArrow: Arrow[Int, Int] = ??? Arrow[Int].flatMap { case 0 => 0 case i => someArrow(a) }
A Task
is a specific case of an Arrow without
inputs.
A Task
is a specific case of an Arrow without
inputs. The package object defines it as:
type Task[+T] = Arrow[Unit, T]
It's the equivalent of Task
/IO
in libraries
like Scalaz 8, Cats Effect, and Monix.
This object provides operations to manipulate Task
instances similarly to how they'd be manipulated using
the Task
companion object.