FunctorFilter 

Scala’s for comprehension allows filtering:

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)

Here’s the typeclass contract for `FunctorFilter`:

@typeclass trait FunctorFilter[F[_]] extends Functor[F] {
  /**
   * A combined [[map]] and [[filter]]. Filtering is handled via `Option`
   * instead of `Boolean` such that the output type `B` can be different than
   * the input type `A`.
   * ....
   *
   **/
  def mapFilter[A, B](fa: F[A])(f: A => Option[B]): F[B]
}

We can use this like this:

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)

This enables the derivative functions/operators collect, flattenOption, and filter:

@typeclass trait FunctorFilter[F[_]] extends Functor[F] {

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

  /**
   * Similar to [[mapFilter]] but uses a partial function instead of a function
   * that returns an `Option`.
   */
  def collect[A, B](fa: F[A])(f: PartialFunction[A, B]): F[B] =
    mapFilter(fa)(f.lift)

  /**
   * "Flatten" out a structure by collapsing `Option`s.
   */
  def flattenOption[A](fa: F[Option[A]]): F[A] = mapFilter(fa)(identity)

  /**
   * Apply a filter to a structure such that the output structure contains all
   * `A` elements in the input structure that satisfy the predicate `f` but none
   * that don't.
   */
  def filter[A](fa: F[A])(f: A => Boolean): F[A] =
    mapFilter(fa)(a => if (f(a)) Some(a) else None)
}

We can use this like this:

scala> def collectEnglish[F[_]: FunctorFilter](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.FunctorFilter[F])F[String]

scala> collectEnglish((1 to 50).toList)
res2: List[String] = List(one, three, ten)

scala> def filterSeven[F[_]: FunctorFilter](f: F[Int]): F[Int] =
         f filter { _.show contains '7' }
filterSeven: [F[_]](f: F[Int])(implicit evidence$1: cats.FunctorFilter[F])F[Int]

scala> filterSeven((1 to 50).toList)
res3: List[Int] = List(7, 17, 27, 37, 47)