Scala 元组的泛型提取&x27;带选项[A]?

Scala 元组的泛型提取&x27;带选项[A]?,scala,shapeless,Scala,Shapeless,给定函数,f,该函数给定一个2元组的选项[a],将非空元组元素放入一个输出列表[a]: def f[A](xs: (Option[A], Option[A])): List[A] = xs match { case (Some(x), Some(y)) => List(x, y) case (None, Some(y)) => List(y) case (Some(x), None) => List(x) case (None,

给定函数,
f
,该函数给定一个2元组的
选项[a]
,将非空元组元素放入一个输出
列表[a]

  def f[A](xs: (Option[A], Option[A])): List[A] = xs match {
    case (Some(x), Some(y)) => List(x, y)
    case (None,    Some(y)) => List(y)
    case (Some(x), None)    => List(x)
    case (None,    None)    => List.empty
  }
如何编写通用的
f
,即
fGen
,以处理任何元组大小,即2到N


也许我可以使用shapeless?

以下代码带有警告:

可以改进

  • 使功能
    f
    类型安全(由于类型擦除仅限于
    选项
  • 避免使用
    a替代

以下是我的(不完美)解决方案:

@ object Tuple2List {
    import shapeless._
    import syntax.std.tuple._
    import ops.hlist.ToTraversable
    trait Imp[A] {
      def apply[P <: Product, L <: HList](p: P)
               (implicit gen: Generic.Aux[P, L], 
                lub: LUBConstraint[L, Option[A]], 
                trav: ToTraversable.Aux[L, List, Option[A]]): List[A] =
        gen.to(p).toList.flatMap(_.toList)
    }
    def apply[A] = new Imp[A]{ }
  }
defined object Tuple2List
@ val xs = (Option(1), None, Option(2))
xs: (Option[Int], None.type, Option[Int]) = (Some(1), None, Some(2))

@ Tuple2List[Int](xs)
res9: List[Int] = List(1, 2)
@ val ys = (Option(1), None, Option(2), None, Option(3))
ys: (Option[Int], None.type, Option[Int], None.type, Option[Int]) = (Some(1), None, Some(2), None, Some(3))
@ Tuple2List[Int](ys)
res11: List[Int] = List(1, 2, 3)
@object Tuple2List{
进口不成形_
导入syntax.std.tuple_
导入ops.hlist.ToTraversable
特质Imp[A]{

def apply[P

这是@Eastsun解决方案的一个变体,它不需要类型参数。感谢@Eastsun指出可以使用

list.map(ev)
而不是强制转换


def tuple2list[P你需要对元组的算术进行抽象,这是Shapess提供的东西之一。看这个:你有一个用例吗?虽然我可以将兴趣视为一种智力练习,但很难理解为什么人们会想使用这样不同大小的元组。作为你的激励示例,这在(我认为是)元组的误用,假设不同元组元素之间存在我认为不应该存在的连接(例如,在本例中,
(None,Some(y)
)和
(Some(x),None)
返回相同的“形状”结果(单个元素列表)。无论如何,我只是个人意见。好的观点,@TheArchetypalPaul。目前没有精确的用例。我有一个可能的用例,但我需要充实它。通过将
设置为[List[Option[a]
设置为
map(ev)
@ object Tuple2List {
    import shapeless._
    import syntax.std.tuple._
    import ops.hlist.ToTraversable
    trait Imp[A] {
      def apply[P <: Product, L <: HList](p: P)
               (implicit gen: Generic.Aux[P, L], 
                lub: LUBConstraint[L, Option[A]], 
                trav: ToTraversable.Aux[L, List, Option[A]]): List[A] =
        gen.to(p).toList.flatMap(_.toList)
    }
    def apply[A] = new Imp[A]{ }
  }
defined object Tuple2List
@ val xs = (Option(1), None, Option(2))
xs: (Option[Int], None.type, Option[Int]) = (Some(1), None, Some(2))

@ Tuple2List[Int](xs)
res9: List[Int] = List(1, 2)
@ val ys = (Option(1), None, Option(2), None, Option(3))
ys: (Option[Int], None.type, Option[Int], None.type, Option[Int]) = (Some(1), None, Some(2), None, Some(3))
@ Tuple2List[Int](ys)
res11: List[Int] = List(1, 2, 3)