N元组选项的N元组

时间:2015-05-13 05:34:37

标签: 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-Tuples的一般解决方案。提出的答案专门针对2元组。

我是不是写了一个宏,还是可以将Shapeless / Scalaz保存一天?

1 个答案:

答案 0 :(得分:5)

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(或者更确切地说是甚至更多类型级版本)具有静态类型为SomeNone的元素的元组,并获得静态类型为SomeNone的结果。这可能在某些情况下有应用,但一般情况下,如果你有一个静态输入Some[A]的东西,你应该只将其表示为A,我猜你可能想要更少的类型级版本。

请注意,shapeless-contrib Sequencer适用于任何应用仿函数,而不仅仅是Option,这意味着您可以轻松地重写我的foo以获取{{1}键入参数并返回F[_]: Applicative。您也可以使用仅在F[T]上运行的自己不那么通用的版本,并且实现可能比shapeless-contrib更简单。

相关问题