是否有类似 Collectable 类型类的东西?

Is there something like Collectable typeclass?

我注意到 OptionOptionTfs2.Stream 等容器具有以下方法:

def collect[B](f: PartialFunction[A, B])(implicit F: Functor[F]): OptionT[F, B] =
    OptionT(F.map(value)(_.collect(f)))

所以我很好奇是否有类似 Collectable typeclass:

的东西
trait Collectable[F[_]] {
  def collect[A, B](fa: F[A])(pf: PartialFunction[A, B]): F[B]
}

它对我来说似乎很有用,而且实现起来也很简单,但是无论如何 cats/scalaz 中已经包含了具有类似功能的东西吗?

Foldable 类型类似乎非常接近您想要的。它有一个方法 collectFirst,签名如下:

  def collectFirst[A, B](fa: F[A])(pf: PartialFunction[A, B]): Option[B] =

和一个奇怪的实现:

    foldRight(fa, Eval.now(Option.empty[B])) { (a, lb) =>
      // trick from TraversableOnce, 
      // used to avoid calling both isDefined and apply (or calling lift)
      val x = pf.applyOrElse(a, sentinel)
      if (x.asInstanceOf[AnyRef] ne sentinel) Eval.now(Some(x.asInstanceOf[B]))
      else lb
    }.value

其中 sentinel 是一个奇怪的小函数,它本身总是 returns:

private val sentinel: Function1[Any, Any] = 
  new scala.runtime.AbstractFunction1[Any, Any]{ 
    def apply(a: Any) = this 
  }

最后两个代码片段应该提供一些动机来避免多次重新实现 collectFirst