我的直觉告诉我,在一般情况下,只有宏或复杂类型的体操才能解决这个问题。 Shapeless 或 Scalaz 可以在这里帮助我吗?这是 N=2 问题的具体实例,但我正在寻找的解决方案适用于所有合理的 N 值:
foo((Some(1), Some("bar"))) == Some((1, "bar"))
foo((None, Some("bar"))) == None
foo((Some(1), None)) == None
同样,这不是 this question 的副本。 ,因为我正在寻找 N 元组的通用解决方案。那里提出的答案专门针对 2 元组。
我是在写一个宏,还是 Shapeless/Scalaz 可以挽救这一天?
最佳答案
shapeless-contrib使这很容易:
import shapeless._, ops.hlist.Tupler, contrib.scalaz._, scalaz._, Scalaz._
def foo[T, L <: HList, O <: HList](t: T)(implicit
gen: Generic.Aux[T, L],
seq: Sequencer.Aux[L, Option[O]],
tup: Tupler[O]
): Option[tup.Out] = seq(gen.to(t)).map(tup(_))
这要求参数中的元素静态类型为
Option
:scala> foo((some(1), some("bar")))
res0: Option[(Int, String)] = Some((1,bar))
scala> foo((none[Int], some("bar")))
res1: Option[(Int, String)] = None
scala> foo((some(1), none[String]))
res2: Option[(Int, String)] = None
正如 Alexandre Archambault 在 Gitter 上提到的,也可以写一个 type-level version (或者更确切地说,我猜是一个更类型级别的版本),您可以在其中使用静态类型为
Some
的元素的元组。或 None
并获得静态类型为 Some
的结果或 None
.这在某些情况下可能有应用程序,但一般来说,如果您将某些内容静态输入为 Some[A]
您应该将其表示为 A
,我猜你可能想要较少类型级别的版本。请注意 shapeless-contrib 的
Sequencer
适用于任何应用仿函数,而不仅仅是 Option
,这意味着你可以很容易地重写我的 foo
拿个F[_]: Applicative
输入参数并返回 F[T]
.您也可以推出自己的不太通用的版本,该版本仅适用于 Option
,并且实现可能比 shapeless-contrib 中的实现要简单一些。
关于scala - N-Tuple of Options to Option of N-Tuple,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30206454/