scala - N-Tuple of Options to Option of N-Tuple

标签 scala scalaz shapeless

我的直觉告诉我,在一般情况下,只有宏或复杂类型的体操才能解决这个问题。 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/

相关文章:

scala - 为 A 和 B 类型创建 given 的最简单方法是什么?

scala - 在 Scala 中转换仿函数 (F[A] => G[A])(cats 或 scalaz)

基于 Scala 类型的属性提取器 - Getter only Lens?

scala - 如何过滤列表[选项]中的“无”?

scala - 用于包装不纯方法的效果?

Scala 组合函数不会终止

scala - 如何在 Scala 中表示案例类的部分更新?

scala - 使用 Scala Shapeless 证明自然数加法的结合性

java - 用java提升框架

scala - 通用类型约束 ":<:"和 ":+:"在这个 Scala 示例中意味着什么?