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

时间:2018-08-27 20:20:19

标签: scala functional-programming scalaz scala-cats

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

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

所以我很好奇是否存在类似Collectable类型的类:

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

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

1 个答案:

答案 0 :(得分:3)

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是一个奇怪的小函数,总是返回自身:

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

最后两个代码段应该提供一些动力,使它们不会多次重新实现collectFirst