Syntax

Implicit syntax

Fetch provides implicit syntax to lift any value to the context of a Fetch in addition to the most common used combinators active within Fetch instances.

Pure

Plain values can be lifted to the Fetch monad with value.fetch:

Executing a pure fetch doesn't query any data source, as expected.

42.fetch.runA[Id] shouldBe res0

Error

Errors can also be lifted to the Fetch monad via exception.fetch.

val fetchFail: Fetch[Int] = new Exception("Something went terribly wrong").fetch
Try(fetchFail.runA[Id]).isFailure shouldBe res0

Join

We can compose two independent fetches with fetch1.join(fetch2).

val fetchJoined: Fetch[(Post, User)] = getPost(1).join(getUser(2))
fetchJoined.runA[Id] shouldBe res0

RunA

Run directly any fetch with fetch1.runA[M[_]].

1.fetch.runA[Id] shouldBe res0

RunE

Discard results and get the fetch environment with fetch1.runE[M[_]].

1.fetch.runE[Id].isInstanceOf[FetchEnv] shouldBe res0

RunF

Obtain results and get the fetch environment with fetch1.runF[M[_]].

val (env, result) = 1.fetch.runF[Id]

result shouldBe res0
env.isInstanceOf[FetchEnv] shouldBe res1

Companion object

We’ve been using Cats’ syntax and fetch.syntax throughout the examples since it’s more concise and general than the methods in the Fetch companion object. However, you can use the methods in the companion object directly.

Note that using cats syntax gives you a plethora of combinators, much richer that what the companion object provides.

Pure

Plain values can be lifted to the Fetch monad with Fetch#pure:

Executing a pure fetch doesn’t query any data source, as expected.

val fetchPure: Fetch[Int] = Fetch.pure(42)

Fetch.run[Id](fetchPure) shouldBe res0

Error

Errors can also be lifted to the Fetch monad via Fetch#error.

val fetchFail: Fetch[Int] = Fetch.error(new Exception("Something went terribly wrong")) Note that interpreting an errorful fetch to Id will throw the exception.

 Fetch.run[Id](fetchFail)
fetch.UnhandledException: java.lang.Exception: Something went terribly wrong

Join

We can compose two independent fetches with Fetch#join.

If the fetches are to the same data source they will be batched; if they aren’t, they will be evaluated at the same time.

val fetchJoined: Fetch[(Post, User)] = Fetch.join(getPost(1), getUser(2))

Fetch.run[Id](fetchJoined) shouldBe res0

Sequence

The Fetch#sequence combinator turns a List[Fetch[A]] into a Fetch[List[A]], running all the fetches concurrently and batching when possible.

Note that Fetch#sequence is not as general as the sequence method from Traverse, but performs the same optimizations.

val fetchSequence: Fetch[List[User]] = Fetch.sequence(List(getUser(1), getUser(2), getUser(3)))

Fetch.run[Id](fetchSequence) shouldBe res0

Traverse

The Fetch#traverse combinator is a combination of map and sequence.

Note that Fetch#traverse is not as general as the traverse method from Traverse, but performs the same optimizations.

val fetchTraverse: Fetch[List[User]] = Fetch.traverse(List(1, 2, 3))(getUser)

Fetch.run[Id](fetchTraverse) shouldBe res0