Преобразование списка параметров в вариант списка с помощью Scalaz

StackOverflow https://stackoverflow.com/questions/2569014

  •  24-09-2019
  •  | 
  •  

Вопрос

Я хочу преобразовать общий кодовый код в общий кодовый код.Тип сигнатуры функции

родовое слово

Ожидаемое поведение - преобразовать список, содержащий только List[Option[T]]s, в Option[List[T]], содержащий список элементов внутри элементов Some's.С другой стороны, если во входном списке есть хотя бы один Some, ожидаемым поведением будет просто возврат Some.Например:

родовое слово

Пример реализации без скаляза:

родовое слово

Я помню, как где-то видел похожий пример, но с использованием Scalaz для упрощения кода.Как бы это выглядело?


Чуть более лаконичная версия, использующая код Scala2.8 None, но без Scalaz:

родовое слово
Это было полезно?

Решение

В Scalaz есть функция, которая превращает генерирующий кодовый код в общий кодовый код. Это генерирующий код. Чтобы получить код List[Option[A]] в случае, если какой-либо из элементов является Option[List[A]] и sequence, если все элементы являются None, вы можете просто сделать следующее:

родовое слово

Этот метод фактически превращает None в Some[List[A]], учитывая, что существует реализация Some и F[G[A] (G[F[A]] и Traverse[F] удовлетворяют обоим и предоставляются этим импортом).

Семантика Applicative[G] такова, что если какой-либо из элементов Option из Lists является Applicative[Option], то код List также будет Option. Если вы хотите получить список всех значений None независимо от того, являются ли другие значения sequence, вы можете сделать следующее:

родовое слово

Вы можете обобщить это для любого None, который также формирует Some (None может быть одним из них):

родовое слово

Другие советы

По какой-то причине вам не нравится

родовое слово

?Вероятно, это самый короткий вариант в Scala без Scalaz.

Хотя код Applicative[Option] в Scalaz не позволяет напрямую использовать код MA#sequence, вы также можете получить код Applicative из кода Monoid. Это удобно с помощью MA#foldMapDefault или MA#collapse.

В этом случае мы используем общий кодовый код. Сначала мы выполняем внутреннюю карту (Monoid[Option[List[Int]]), чтобы обернуть отдельные общие кодовые коды в общие коды одного элемента.

родовое слово

Абстрагирование от MA#∘∘ к любому контейнеру с экземплярами для Int, List и List:

родовое слово

К сожалению, попытка скомпилировать этот код в настоящее время вызывает либо # 2741 , либо отправляет компилятор в бесконечный цикл.

ОБНОВЛЕНИЕ Чтобы избежать двойного обхода списка, мне следовало использовать Traverse:

родовое слово

Этот ответ был основан на исходном запросе о том, что пустой список или список, содержащий только общие кодовые коды, должен возвращать общий кодовый код. Кстати, это лучше всего было бы смоделировать с помощью типа Pointed - Monoid гарантирует наличие хотя бы одного элемента.

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

родовое слово

У меня это сработало.Надеюсь, это правильное решение.

Он возвращает None, если одна из опций в списке - None, в противном случае она возвращает Option of List [A]

родовое слово

Запуск генерирующего кода метки и добавление сгенерировать код кода в стандартную библиотеку , вариант для Ответ Рекса Керра :

родовое слово

или, если на карту поставлена производительность (во избежание неявного преобразования Scala 2.13 из Option::unless в flatten):

родовое слово
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top