Эффективный способ создания абстрактной коллекции с кошками - PullRequest
0 голосов
/ 05 декабря 2018

У меня есть код, который использует Monix Observable для потоковой обработки файла.Чтобы проверить этот код, я бы хотел, чтобы операции, которые я выполняю на Observable, были независимыми от типа, поэтому я также могу выполнять их с любой другой структурой данных, такой как List.Вот почему я написал следующий код для абстракции базовой структуры данных:

def permutations[F[_] : Applicative : FunctorFilter : SemigroupK](chars: F[Char]): F[F[Char]] = {
  Range.inclusive('a', 'z').map(_.toChar)
    .map { c ⇒
      FunctorFilter[F].filter(chars)(Character.toLowerCase _ andThen (_ != c))
    }
    .map(Applicative[F].pure)
    .reduceLeft(SemigroupK[F].combineK)
}

Меня беспокоит то, что этот код создает много промежуточных структур данных.Есть ли класс типов, который я мог бы использовать, чтобы сделать этот процесс более эффективным?Что-то, что поднимает одну структуру данных в другую без слишком больших накладных расходов, как LiftIO, но для коллекций элементов?

1 Ответ

0 голосов
/ 05 декабря 2018

Не похоже, что кошкам есть что предложить для этого.И monix не лучше, он реализует лишь несколько классов типов от кошек.

Итак, я бы лучше всего сам определил такие классы типов:

import monix.execution.Scheduler.Implicits.global
import cats._
import cats.implicits._
import monix.reactive._

object Test {

  def main(args: Array[String]): Unit = {

    println(permutations(List('a', 'b', 'c')))

    permutations(Observable('a', 'b', 'c')).foreach{c =>
      print("Observable(")
      c.foreach(c1 => print(c1 + " "))
      print(") ")
    }
  }

  def permutations[F[_] : Applicative](chars: F[Char])(implicit seq: Sequence[F], fil: Filter[F]): F[F[Char]] = {

    val abc = seq.fromIterable(
      Range.inclusive('a', 'z').map(_.toChar)
    )

    abc.map(c => fil.filter(chars)(_ != c))
  }

  trait Sequence[F[_]] {

    def fromIterable[A](f: Iterable[A]): F[A]
  }

  implicit val listSequence: Sequence[List] = new Sequence[List] {

    def fromIterable[A](f: Iterable[A]): List[A] = f.toList
  }

  implicit val observableSequence: Sequence[Observable] = new Sequence[Observable] {

    def fromIterable[A](f: Iterable[A]): Observable[A] = Observable.fromIterable(f)
  }

  trait Filter[F[_]] {

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

  implicit val observableFilterFunctor: Filter[Observable] = new Filter[Observable] {

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

  implicit val listFilterFunctor: Filter[List] = new Filter[List] {

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

}

Результат:

List(List(b, c), List(a, c), List(a, b), List(a, b, c), List(a, b, c), List(a, b, c), List(a, b, c), List(a, b, c), List(a, b, c), List(a, b, c), List(a, b, c), List(a, b, c), List(a, b, c), List(a, b, c), List(a, b, c), List(a, b, c), List(a, b, c), List(a, b, c), List(a, b, c), List(a, b, c), List(a, b, c), List(a, b, c), List(a, b, c), List(a, b, c), List(a, b, c), List(a, b, c))
Observable(b c ) Observable(a c ) Observable(a b ) Observable(a b c ) Observable(a b c ) Observable(a b c ) Observable(a b c ) Observable(a b c ) Observable(a b c ) Observable(a b c ) Observable(a b c ) Observable(a b c ) Observable(a b c ) Observable(a b c ) Observable(a b c ) Observable(a b c ) Observable(a b c ) Observable(a b c ) Observable(a b c ) Observable(a b c ) Observable(a b c ) Observable(a b c ) Observable(a b c ) Observable(a b c ) Observable(a b c ) Observable(a b c ) 

К сожалению, я не мог заставить это работать на scalafiddle или scastie, потому что оба не предлагают правильные версии для кошек (1.5.0) и monix (3.0.0-M3).

Я все еще надеюсьэто помогает.

...