mapN over composed Apply

馋奶兔 提交于 2020-01-04 04:40:06

问题


I know that I can compose Apply to work with nested structures, like in

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)
}

However, is there a way to convince the compiler to accept (o1, o2, o3).mapN(f) instead of Apply[List].compose[Option].map3(o1, o2, o3)(f), so that mapN gets applied using the composed Apply?


回答1:


This is exactly what cats.data.Nested is for:

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
}

(Note that you will need to enable the -Ypartial-unification compiler flag for the code above to compile. Alternatively you could add some type parameters, but off the top of my head I'm not sure exactly where they'd be required, and if you're doing anything with Cats -Ypartial-unification is pretty much necessary, anyway.)

You could also just make the composed instance available implicitly:

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)

This really isn't ideal, though—it's non-standard and extremely fragile (e.g. the type aliases are necessary to guide resolution).

In my view your best bet is just to write out Apply[List].compose[Option] explicitly and skip the fancy tuple syntax, but if you really have to have the fancy tuple syntax, go with Nested.



来源:https://stackoverflow.com/questions/55199931/mapn-over-composed-apply

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!