加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala:具有多种来源和异构类型的交叉(笛卡尔)产品

发布时间:2020-12-16 18:16:01 所属栏目:安全 来源:网络整理
导读:我正在尝试构建不同(但每个同类)类型的遍历的多个交叉产品.期望的返回类型是元组的遍历,其类型与输入遍历中的类型匹配.例如: List(1,2,3) cross Seq("a","b") cross Set(0.5,7.3) 这应该给Traversable [(Int,String,Double)]提供三个来源的所有可能组合.只
我正在尝试构建不同(但每个同类)类型的遍历的多个交叉产品.期望的返回类型是元组的遍历,其类型与输入遍历中的类型匹配.例如:

List(1,2,3) cross Seq("a","b") cross Set(0.5,7.3)

这应该给Traversable [(Int,String,Double)]提供三个来源的所有可能组合.只合并两个来源的情况很好answered here.给出的想法是:

implicit class Crossable[X](xs: Traversable[X]) {
  def cross[A](ys: Traversable[A]) = for { x <- xs; y <- ys } yield (x,y)
}

那里的评论简要地提到了更多来源的问题,但我希望找到一种不依赖于无形或scalaz的解决方案(另一方面,我不介意有一些样板扩展到Tuple22).我想做的是如下:

implicit class Crossable[X](xs: Traversable[X]) {
  def cross[A](ys: Traversable[A]) = for { x <- xs; y <- ys } yield (x,y)
  def cross[A,B](ys: Traversable[(A,B)]) = // ... extend all Tuple2's in ys with x in xs to Tuple3's
  def cross[A,B,C](ys: Traversable[(A,C)]) = // ...
  // ...
}

由于类型擦除,这显然不起作用(不幸的是,可能需要在上面的示例中使用括号,因为交叉将是正确的关联).

我的问题是:是否有可能利用Scala 2.10的反射功能来解决问题?通常,将A和X与各种元组类型(及其类型参数,这似乎具有挑战性)相匹配,并将它们合并到更大的元组应该提供满足关联法则的解决方案,对吧?

解决方法

我有一个想法,想出了这个:

trait Crosser[A,C] {
  def cross( as: Traversable[A],bs: Traversable[B] ): Traversable[C]
}

trait LowPriorityCrosserImplicits {
  private type T[X] = Traversable[X]

  implicit def crosser2[A,B] = new Crosser[A,(A,B)] {
    def cross( as: T[A],bs: T[B] ): T[(A,B)] = for { a <- as; b <- bs } yield (a,b)
  }
}

object Crosser extends LowPriorityCrosserImplicits {
  private type T[X] = Traversable[X]

  implicit def crosser3[A,C] = new Crosser[(A,B),C,C)] {
    def cross( abs: T[(A,B)],cs: T[C] ): T[(A,C)] = for { (a,b) <- abs; c <- cs } yield (a,b,c)
  }

  implicit def crosser4[A,D] = new Crosser[(A,C),D,D)] {
    def cross( abcs: T[(A,C)],ds: T[D] ): T[(A,D)] = for { (a,c) <- abcs; d <- ds } yield (a,c,d)
  }

  // and so on ...
}

implicit class Crossable[A](xs: Traversable[A]) {
  def cross[B,C](ys: Traversable[B])(implicit crosser: Crosser[A,C]): Traversable[C] = crosser.cross( xs,ys )
}

主要思想是将工作推迟到类型类(Crosser)并简单地通过专门针对具有相应arity减去1的元组的Traversable来实现所有不同的arities.
在REPL中进行一些测试:

scala> List(1,7.3)
res10: Traversable[(Int,Double)] = List((1,a,0.5),(1,7.3),(2,(3,7.3))

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读