Skip to content

Instantly share code, notes, and snippets.

@tg44
Created February 1, 2020 16:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tg44/c0e20c64714c60df2661eb1fcd73ab83 to your computer and use it in GitHub Desktop.
Save tg44/c0e20c64714c60df2661eb1fcd73ab83 to your computer and use it in GitHub Desktop.
Tuples vs functions vs generics
import scala.concurrent.{ExecutionContext, Future}
import cats.implicits._
import shapeless.ops.tuple.IsComposite
import concurrent.ExecutionContext.Implicits._
import shapeless.ops.tuple._
def unwrap0[I, E, O](uf: I => Future[Either[E, O]]): I => Future[Either[E, O]] = uf
def unwrap1[I, K, E, O](uf: I => K => Future[Either[E, O]]): ((I, K)) => Future[Either[E, O]] = i => uf(i._1)(i._2)
def unwrapN[IN_TUPLE, OUT_TUPLE, I, E, O](uf: I => OUT_TUPLE => Future[Either[E, O]])
(implicit ic: IsComposite.Aux[IN_TUPLE, I, OUT_TUPLE])
: IN_TUPLE => Future[Either[E, O]] =
{inTuple =>
uf(ic.head(inTuple))(ic.tail(inTuple))
}
def withF1[I, K, E, A, O](af: I => Future[Either[E, A]])
(uf: A => K => Future[Either[E, O]])
(implicit ec: ExecutionContext)
: ((I, K)) => Future[Either[E, O]] =
{ i =>
af(i._1).flatMap {
case Left(e) => Future.successful(Left(e))
case Right(u) =>
uf(u)(i._2)
}
}
def withFN[IN_TUPLE, OUT_TUPLE, I, E, A, O](af: I => Future[Either[E, A]])
(uf: A => OUT_TUPLE => Future[Either[E, O]])
(implicit ic: IsComposite.Aux[IN_TUPLE, I, OUT_TUPLE], ec: ExecutionContext)
: IN_TUPLE => Future[Either[E, O]] =
{ inTuple =>
val t = ic.head(inTuple)
af(t).flatMap {
case Left(e) => Future.successful(Left(e))
case Right(u) =>
val outTuple = ic.tail(inTuple)
uf(u)(outTuple)
}
}
def authFunc(b: Boolean): Future[Either[String, Int]] = if(b) Future.successful(1.asRight[String]) else Future.successful("error".asLeft[Int])
def appLogic(id: Int, name: String, s1: String, s2: String): Future[Either[String, Int]] = Future.successful(1.asRight[String])
val endpointLogic: ((Boolean, String)) => Future[Either[String, Int]] = {
withF1(authFunc){ userId =>
unwrap0 { name =>
appLogic(userId, name, "", "")
}
}
}
val endpointLogic2: ((Boolean, String, String)) => Future[Either[String, Int]] = {
withFN(authFunc){ userId =>
unwrap1 { name: String =>
unwrap0 { email: String =>
appLogic(userId, name, email, "")
}
}
}
}
val endpointLogic3: ((Boolean, String, String, String)) => Future[Either[String, Int]] = {
withFN(authFunc){ userId: Int =>
unwrapN { dummy: String =>
unwrap1 { name: String =>
unwrap0 { email: String =>
appLogic(userId, name, email, dummy)
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment