Note that there are some explanatory texts on larger screens.

plurals
  1. POCombining Futures, Eithers and Options in for comprehensions
    primarykey
    data
    text
    <p>I have a collection of methods that return different types:</p> <pre><code>Either[ErrorResponse, X] Future[Either[ErrorResponse, X]] Option[ErrorResponse] </code></pre> <p>These methods need the result from a previous method to perform their computation. The methods:</p> <pre><code>type Parameters = Map[String, String] // allows me to flatmap on an either implicit def toRightProjection[Failure, Success](e: Either[Failure, Success]) = e.right // converts anything to a future implicit def toFuture[T](t: T) = Future.successful(t) // retrieves the request paramters from the given request def requestParameters(request: RequestHeader): Either[ErrorResponse, Parameters] = ??? // retrieves the response type from the given parameters def responseType(p: Parameters): Either[ErrorResponse, String] = ??? // retrieves the client id from the given parameters def clientId(p: Parameters): Either[ErrorResponse, String] = ??? // retrieves the client using the given client id def client(clientId: String): Future[Either[ErrorResponse, Client]] = ??? // validates the response type of the client def validateResponseType(client: Client, responseType: String): Option[ErrorResponse] = ??? </code></pre> <p>I can the wire them together with the following for comprehension (note that I wrote down some types to clarify the contents of specific parts of the computation).</p> <pre><code>val result: Either[ErrorResponse, Future[Either[ErrorResponse, Client]]] = for { parameters &lt;- requestParameters(request) clientId &lt;- clientId(parameters) responseType &lt;- responseType(parameters) } yield { val result: Future[Either[ErrorResponse, Either[ErrorResponse, Client]]] = for { errorOrClient &lt;- client(clientId) client &lt;- errorOrClient } yield validateResponseType(client, responseType).toLeft(client) result.map(_.joinRight) } val wantedResult: Future[Either[ErrorResponse, Client]] = result.left.map(Future successful Left(_)).merge </code></pre> <p>The above code is quite messy and I feel this can be done differently. I read about monads and monad transformers. The concept of those is very new to me and I can not get my head around it.</p> <p>Most of the examples only deal with two types of results: <code>Either[X, Y]</code> and <code>Future[Either[X, Y]]</code>. I still find it very hard to bend my mind around it.</p> <p><strong>How can I write a nice and clean for comprehension that replaces the above one?</strong></p> <p>Something like this would be awesome (I am not sure if that is even possible):</p> <pre><code>val result: Future[Either[ErrorResponse, Client]] = for { parameters &lt;- requestParameters(request) clientId &lt;- clientId(parameters) responseType &lt;- responseType(parameters) client &lt;- client(clientId) _ &lt;- validateResponseType(client, responseType) } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload