mapN над составленным Применить

Я знаю что могу сочинять Apply работать с вложенными структурами, как в

def mapAll[A, B, C, D](o1: List[Option[A]],
                       o2: List[Option[B]],
                       o3: List[Option[C]])
                      (f: (A, B, C) => D)
: List[Option[D]] = {
  import cats._
  import cats.implicits._
  Apply[List].compose[Option].map3(o1, o2, o3)(f)
}

Однако есть ли способ убедить компилятор принять (o1, o2, o3).mapN(f) вместо Apply[List].compose[Option].map3(o1, o2, o3)(f), чтобы mapN применяется с использованием сложного Apply?

1 ответ

Решение

Это именно то, что cats.data.Nested для:

def mapAll[A, B, C, D](o1: List[Option[A]],
                       o2: List[Option[B]],
                       o3: List[Option[C]])
                      (f: (A, B, C) => D)
: List[Option[D]] = {
  import cats.data.Nested
  import cats.instances.list._, cats.instances.option._
  import cats.syntax.apply._

  (Nested(o1), Nested(o2), Nested(o3)).mapN(f).value
}

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

Вы также можете просто сделать составной экземпляр доступным неявно:

import cats.Apply
import cats.instances.list._, cats.instances.option._
import cats.syntax.apply._

type ListOption[x] = List[Option[x]]

implicit val listOptionApply: Apply[ListOption] = Apply[List].compose[Option]

def mapAll[A, B, C, D](o1: ListOption[A],
                       o2: ListOption[B],
                       o3: ListOption[C])
                      (f: (A, B, C) => D)
: List[Option[D]] = (o1, o2, o3).mapN(f)

Это действительно не идеальный вариант - он нестандартный и чрезвычайно хрупкий (например, псевдонимы типов необходимы для определения разрешения).

На мой взгляд, ваш лучший выбор - просто написать Apply[List].compose[Option] явно и пропустите причудливый синтаксис кортежей, но если вам действительно нужен причудливый синтаксис кортежей, переходите к Nested,

Другие вопросы по тегам