Last active
May 4, 2016 06:09
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) | |
} | |
} |
also http://stackoverflow.com/questions/3855595/what-is-the-scala-identifier-implicitly was a good read
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
see also http://blogs.atlassian.com/2013/09/scala-types-of-a-higher-kind/