ho una collezione di metodi che restituiscono tipi diversi:Combinando Futures, eithers e opzioni in espressioni for
Either[ErrorResponse, X]
Future[Either[ErrorResponse, X]]
Option[ErrorResponse]
Questi metodi hanno bisogno il risultato di un metodo precedente per svolgere il loro calcolo. I metodi:
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] = ???
posso filo insieme con quanto segue per comprensione (nota che ho annotato alcuni tipi di chiarire il contenuto di parti specifiche del calcolo).
val result: Either[ErrorResponse, Future[Either[ErrorResponse, Client]]] =
for {
parameters <- requestParameters(request)
clientId <- clientId(parameters)
responseType <- responseType(parameters)
} yield {
val result: Future[Either[ErrorResponse, Either[ErrorResponse, Client]]] =
for {
errorOrClient <- client(clientId)
client <- errorOrClient
} yield validateResponseType(client, responseType).toLeft(client)
result.map(_.joinRight)
}
val wantedResult: Future[Either[ErrorResponse, Client]] =
result.left.map(Future successful Left(_)).merge
Il codice sopra riportato è piuttosto disordinato e ritengo che ciò possa essere fatto in modo diverso. Ho letto di monadi e trasformatori monadi. Il concetto di quelli è molto nuovo per me e non riesco a capirlo.
La maggior parte degli esempi riguarda solo due tipi di risultati: Either[X, Y]
e Future[Either[X, Y]]
. Trovo ancora molto difficile piegare la mente intorno ad esso.
Come posso scrivere un testo piacevole e pulito per la comprensione che sostituisce il precedente?
Qualcosa di simile sarebbe fantastico (non sono sicuro se questo è ancora possibile):
val result: Future[Either[ErrorResponse, Client]] =
for {
parameters <- requestParameters(request)
clientId <- clientId(parameters)
responseType <- responseType(parameters)
client <- client(clientId)
_ <- validateResponseType(client, responseType)
}
maggiore documentazione su questo argomento [trasformatori Monade e monadi libero] (https://github.com/EECOLOR/scala-clean-code-patterns/blob/master/src/main/scala/processes/ README.md) – EECOLOR