Skip to content

Instantly share code, notes, and snippets.

@tifletcher
Last active May 4, 2016 06:09
Show Gist options
  • Save tifletcher/f5a9fc14d76532bf62c63705ef8d52c4 to your computer and use it in GitHub Desktop.
Save tifletcher/f5a9fc14d76532bf62c63705ef8d52c4 to your computer and use it in GitHub Desktop.
Working out a bit of code duplication when working with Future[Option[T]], Future[Seq[T]], etc ... Stuff that you have to map into twice to transform.
package core.liststate
import java.util.UUID
import com.google.inject.Inject
import models.Tables
import services.ListStatesDataService
import scala.concurrent.Future
import scala.language.higherKinds
class ListStateService @Inject()(stateService: ListStatesDataService) {
// import FunctorImplicits._
// private def toListState[A <: Tables.ListStatesRow, F[_]: Functor[F]](given: F[A]): F[ListState] =
// implicitly[Functor[F]].map(given)(a => ListState.apply(a))
import DoubleMappableImplicits._
private def makeListStatesFrom[A <: Tables.ListStatesRow, T[_]: DoubleMappable[Future, T]](futureDbResult: Future[T[A]]) =
implicitly[DoubleMappable[Future, T]].map[A, ListState](futureDbResult)((row: A) => ListState.apply(row))
// def findById(id: UUID): Future[Option[ListState]] = stateService.select(id).map(row => toListState(row))
def findById(id: UUID): Future[Option[ListState]] = makeListStatesFrom(stateService.select(id))
// def findMany(ids: Set[UUID]): Future[Seq[ListState]] = stateService.selectMany(ids).map(row => toListState(row))
def findMany(ids: Set[UUID]): Future[Seq[ListState]] = makeListStatesFrom(stateService.selectMany(ids))
}
object FunctorImplicits {
import scala.language.higherKinds
trait Functor[F[_]] {
def map[A, B](a: F[A])(f: A => B): F[B]
}
implicit object OptionAsFunctor extends Functor[Option] {
override def map[A, B](a: Option[A])(f: (A) => B): Option[B] = a.map(f)
}
implicit object SeqAsFunctor extends Functor[Seq] {
override def map[A, B](a: Seq[A])(f: (A) => B): Seq[B] = a.map(f)
}
}
object DoubleMappableImplicits {
import scala.language.higherKinds
trait DoubleMappable[OUTER[_] , INNER[_]] {
def map[A, B](a: OUTER[INNER[A]])(f: (A) => B): OUTER[INNER[B]]
}
implicit object FutureOptionAsDoubleMappable extends DoubleMappable[Future, Option] {
override def map[A, B](a: Future[Option[A]])(f: (A) => B): Future[Option[B]] = a.map(o => o.map(f))
}
implicit object FutureSeqAsDoubleMappable extends DoubleMappable[Future, Seq] {
override def map[A, B](a: Future[Seq[A]])(f: (A) => B): Future[Seq[B]] = a.map(o => o.map(f))
}
}
@tifletcher
Copy link
Author

@tifletcher
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment