Транзитивный функтор с произведением двух аппликативов в Scala

Вопрос или проблема

Я пытался пройтись по структуре данных в Scala и сделать две вещи одновременно. Я использовал библиотеку Cats для этого. Вот небольшой пример, который не компилируется. Я не понимаю, как мне это сделать. Любая помощь будет очень ценна.

import cats.data.Tuple2K
import cats.data.Const
import cats.instances.list._
import cats.syntax.traverse._

List("A", "BB", "CCC").traverse[Tuple2K[[x] =>> Const[Int, x], [x] =>> Const[Int, x], Nothing],    Nothing]{
 case str => 
   Tuple2K[[x] =>> Const[Int, x], [x] =>> Const[Int, x], Nothing](Const(1), Const(str.size)) 
} 

Инструменты выдают следующую ошибку:

Найдена: cats.data.Tuple2K[[x] =>> cats.data.Const[Int, x], [x] =>> cats.data.Const[Int, x], Nothing]

Требуется: cats.data.Tuple2K[[x] =>> cats.data.Const[Int, x], [x] =>> cats.data.Const[Int, x], Nothing][Nothing]

Я пытаюсь получить как размер проходимого объекта (вышеупомянутого списка в моем примере), так и выполнить некоторые вычисления на основе содержимого в одном проходе, в отличие от того, чтобы проходить по списку дважды.

Ответ или решение

Для решения проблемы, описанной в вопросе, необходимо более детально рассмотреть использование модуля Cats для создания и работы сTraversable functor, который комбинирует два applicative контекста. Давайте разберем вашу задачу поэтапно.

Проблематика

Вы стремитесь одновременно вычислить размер каждой строки в списке и общее количество строк, не проходя по списку дважды. Это важная задача, поскольку операция двойного обхода может негативно сказаться на производительности.

Ошибка компиляции

Ошибка, которую вы получаете, зависит от определения и использования Tuple2K. Ваша попытка создать Tuple2K не совпадает с ожидаемым типом из-за разницы в параметрах, связанных с полями приложения. В частности, форма, которую вы используете для создания экземпляров Tuple2K, не приводит к ожидаемому типу.

Решение

Обратите внимание, что для решения вашей задачи вы можете воспользоваться комбинированием двух контекстов только в одном обходе с использованием Traversable и Applicative. Рассмотрим вашу задачу в контексте следующего рабочего кода:

import cats.data.Tuple2K
import cats.data.Const
import cats.implicits._
import cats.traverse.Traverse

// Объявляем список строк
val strings = List("A", "BB", "CCC")

// Определяем нашу операцию через traverse
val result = strings.traverse[Tuple2K[Const[Int, *], Const[Int, *], *], Nothing] {
  str =>
    Tuple2K(Const(1), Const(str.length))
}

// Получаем результат
val finalResult = result.map {
  case Tuple2K(totalCount, lengths) =>
    // Это будет Total Count
    val total = totalCount.getConst
    // И здесь получение длин строк
    val strLengths = lengths.getConst.toList
    (total, strLengths)
}

// Показываем финальный результат
println(finalResult)

Пояснение кода

  1. Импорт необходимых модулей: Мы импортируем все необходимые экземпляры типа из библиотеки Cats, что позволяет работать с Traversable и Applicative.

  2. Создание списка строк: Мы объявляем список, на котором будем производить операции.

  3. Использование traverse: Мы используем метод traverse, который позволяет проходить по нашему списку и изменять его элементы, создавая одновременно два значения через Tuple2K (счетчик элементов и длины строк).

  4. Обработка результата: Метод map позволяет обработать полученный Tuple2K, чтобы извлечь общую длину и произвести сбор всех длин строк в список.

Заключение

Это решение позволит эффективно использовать возможности Cats для работы с одним проходом по данным. Используя Tuple2K в сочетании с Const, вы можете аккумулировать различные данные, что значительно оптимизирует производительность вашей функции. Использование функционального подхода, присущего Scala, в этом контексте подчеркивает его мощь и элегантность.

Если у вас есть дополнительные вопросы или вам нужна помощь в других аспектах работы с Cats или Scala, не стесняйтесь задавать их.

Оцените материал
Добавить комментарий

Капча загружается...