HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Too many nested Types?

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
typesnestedtoomany

Problem

I have the following Scala code:

def getLists(token: String, username: String):Future[Try[Seq[Group]]] = {
    val result:Future[Try[JsValue]] = getAPIResult(token, "https://myapi.com/screen_name=" + username)
    result.map( x => convertFromJsValueToObject(x))
  }

  def getSubscriptions(token: String, username: String):Future[Try[Seq[Group]]] = {...} //same as above

  private def getAPIResult(token: String, apiCall: String):Future[Try[JsValue]] = {
    WS.url(apiCall)
    .withHeaders("Authorization" -> ("Bearer " + token))
    .get().map(response =>
       response.status match {
       case 200 => Success(Json.parse(response.body))
       case _ => Failure(new RuntimeException("Web service call failed: " + response.body))
    })
  }

  private def convertFromJsValueToObject(json: Try[JsValue]): Try[Seq[Group]] = {
    json match {
      case Success(v) => {
        Success(v.as[Seq[Group]])
      }
      case Failure(t) => Failure(t)
      }
  }


and I have a third function like this:

def getAllListsAndSubscriptions(token: String, username: String):Future[Try[Seq[Group]]] = {...}


Which is supposed to concatenate the two Seq collections of Group objects together and return them as per the type signature. I'm really struggling to figure out how to do this though, as the types are so deeply nested.

Have I written my code badly or is there another way to do this?

Solution

You should "lift" your functions instead.

For example, instead of defining:

def getSomething(input: V): Future[FinalType] = {
   val intermediate: IntermediaryType = complicatedFunctionReturningFuture(input)
   mappingFunction(intermediate)
}


use

complicatedFunctionReturningFuture(input).map(mappingFunction)


directly in your code.

You can think of map as a method that is lifting a function IntermediaryType => FinalType to a function Future[Intermediary] => Future[FinalType].

If you have a Future[Try[Type]], you can do a "double lifting" (I'm claiming the trademark on that term!):

complicatedFunctionReturningFutureTry(input).map(_.map(mappingFunction))


which lifts the same function IntermediaryType => FinalType to a function Future[Try[Intermediary]] => Future[Try[FinalType]].

Code Snippets

def getSomething(input: V): Future[FinalType] = {
   val intermediate: IntermediaryType = complicatedFunctionReturningFuture(input)
   mappingFunction(intermediate)
}
complicatedFunctionReturningFuture(input).map(mappingFunction)
complicatedFunctionReturningFutureTry(input).map(_.map(mappingFunction))

Context

StackExchange Code Review Q#59477, answer score: 3

Revisions (0)

No revisions yet.