Readerモナドの使い道 [DI]

catsを使用したReaderモナドの使い道例として、DIのサンプル

  trait DbAccessor {
    def select: List[String]
    def count: Int
  }

  object DbAccessorImpl extends DbAccessor {
    override def select: List[String] = {
      // TODO: dbAccess処理
      List.empty
    }
    override def count: Int = {
      // TODO: dbAccess処理
      0
    }
  }

  object DbAccessorMock extends DbAccessor {
    override def select: List[String] = List("a", "c", "d")
    override def count: Int = 5
  }

  val selectR = Reader[DbAccessor, List[String]](db => db.select)
  val countR = Reader[DbAccessor, Int](db => db.count)

  val tupleR = for {
    list <- selectR
    int <- countR
  } yield (int, list)

  // テスト時はmockを使う
  println(tupleR.run(DbAccessorMock)) // (5,List(a, c, d))
  // 実装はdbアクセスする
  println(tupleR.run(DbAccessorImpl)) // (0,List())