走り書き
trait Repository {
type ResultMonad[_]
def fetch(): ResultMonad[Int]
}
class OnMemoryRepository extends Repository {
override type ResultMonad[A] = cats.Id[A]
override def fetch(): ResultMonad[Int] = 3 // 戻り値は適当
}
class RDBRepository extends Repository {
type Connection = String // Stringをコネクションだと思ってください…
override type ResultMonad[A] = Reader[Connection, A]
override def fetch(): ResultMonad[Int] = Reader { _.toInt }
}
import cats.implicits._
class Service[Repo <: Repository](val repo: Repo) { // 型パラメタをなくすとrepositoryの戻り値型が曖昧になってしまう…なぜ…
import repo._
def use()(implicit F: cats.Monad[repo.ResultMonad]): repo.ResultMonad[Int] = for {
a <- repo.fetch()
b <- repo.fetch()
} yield { a + b }
}
val r: Int = new Service(new OnMemoryRepository()).use // => 6
val h: Int = new Service(new RDBRepository()).use.run("3") // => 6
ResultMonadがMonadである保証をしたい、、、