Есть ли что-то вроде коллекционного класса типов? - PullRequest
0 голосов
/ 27 августа 2018

Я заметил, что контейнеры типа Option, OptionT, fs2.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 голосов
/ 27 августа 2018

Класс типов 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 несколько раз.

...