本文介绍了mapN 复合应用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道我可以编写 Apply 来处理嵌套结构,就像在

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

但是,有没有办法说服编译器接受 (o1, o2, o3).mapN(f) 而不是 Apply[List].compose[Option].map3(o1, o2, o3)(f),以便使用组合的 Apply?

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?

推荐答案

这正是 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 是非常必要的,无论如何.)

(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).

在我看来,你最好的办法就是明确写出 Apply[List].compose[Option] 并跳过花哨的元组语法,但如果你真的需要花哨的元组语法,使用 Nested.

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.

这篇关于mapN 复合应用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-30 08:43