FunctorFilter 

Scala の for 内包表記はフィルタリングができる:

scala> import cats._, cats.data._, cats.implicits._
import cats._
import cats.data._
import cats.implicits._
scala> for {
         x <- (1 to 50).toList if x.show contains '7'
       } yield x
res0: List[Int] = List(7, 17, 27, 37, 47)

以下が cats-mtl モジュールの FunctorEmpty 型クラスのコントラクトだ:

trait FunctorEmpty[F[_]] extends Serializable {
  val functor: Functor[F]

  def mapFilter[A, B](fa: F[A])(f: A => Option[B]): F[B]

  def collect[A, B](fa: F[A])(f: PartialFunction[A, B]): F[B]

  def flattenOption[A](fa: F[Option[A]]): F[A]

  def filter[A](fa: F[A])(f: A => Boolean): F[A]
}

このように使うことができる:

scala> import cats.mtl._, cats.mtl.implicits._
import cats.mtl._
import cats.mtl.implicits._
scala> val english = Map(1 -> "one", 3 -> "three", 10 -> "ten")
english: scala.collection.immutable.Map[Int,String] = Map(1 -> one, 3 -> three, 10 -> ten)
scala> (1 to 50).toList mapFilter { english.get(_) }
res1: List[String] = List(one, three, ten)
scala> def collectEnglish[F[_]: FunctorEmpty](f: F[Int]): F[String] =
         f collect {
           case 1  => "one"
           case 3  => "three"
           case 10 => "ten"
         }
collectEnglish: [F[_]](f: F[Int])(implicit evidence$1: cats.mtl.FunctorEmpty[F])F[String]
scala> collectEnglish((1 to 50).toList)
res2: List[String] = List(one, three, ten)
scala> def filterSeven[F[_]: FunctorEmpty](f: F[Int]): F[Int] =
         f filter { _.show contains '7' }
filterSeven: [F[_]](f: F[Int])(implicit evidence$1: cats.mtl.FunctorEmpty[F])F[Int]
scala> filterSeven((1 to 50).toList)
res3: List[Int] = List(7, 17, 27, 37, 47)

Contents

猫番
    1. FunctorFilter