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

scala中使用扁平元组的高阶运算

发布时间:2020-12-16 08:51:41 所属栏目:安全 来源:网络整理
导读:我最近遇到了一个问题.我试图以编译器友好的方式压扁“尾嵌套”元组,我想出了下面的代码: implicit def FS[T](x: T): List[T] = List(x)implicit def flatten[T,V](x: (T,V))(implicit ft: T=List[T],fv: V=List[T]) = ft(x._1) ++ fv(x._2) 上面的代码适用
我最近遇到了一个问题.我试图以编译器友好的方式压扁“尾嵌套”元组,我想出了下面的代码:

implicit def FS[T](x: T): List[T] = List(x)
implicit def flatten[T,V](x: (T,V))(implicit ft: T=>List[T],fv: V=>List[T]) = 
  ft(x._1) ++ fv(x._2)

上面的代码适用于扁平化元组,我称之为“尾嵌套”,如下所示.

flatten((1,2)) -> List(1,2)
flatten((1,(2,3))) -> List(1,2,3)
flatten((1,(3,4)))) -> List(1,3,4)

但是,我试图让我的解决方案更加强大.考虑一个案例,我有一个这些高级“尾嵌套”元组的列表.

val l = List( (1,2),(1,3)),4))) )

推断的类型签名是List [(Int,Any)],这对诸如map之类的操作造成了问题,因为它将失败:

错误:Any =>中没有可用的隐式视图列表[INT]

这个错误对我有意义,因为我在flatten函数中的递归隐式链的性质.但是,我想知道:有没有什么方法可以让我的方法使元组更加强大,以便更高阶函数(如地图网格)很好用?

编辑:

正如Bask.ws指出的那样,产品特性提供了一个很好的解决方案的潜力.以下代码说明了这一点:

def flatten(p: Product): List[_] = p.productIterator.toList.flatMap {x => x match {
  case pr: Product => flatten(pr)
  case _ => List(x)
}}

此新展平调用的结果类型始终为List [Any].如果有一种方法让编译器收紧这个限制,我的问题就会得到解决.与我原来的问题并行,是否有人知道是否有可能实现这一目标?

解决方法

添加了UPD编译时失败解决方案

我有一个可能适合你的解决方案.前3个示例的类型在编译时解析:Int,Tuple2 [Int,Int],Int]].对于您的列表示例,您具有实际类型List [(Int,Any)]的异构列表,您必须在运行时解析第二种类型,或者可以通过宏来完成.因此,您可能希望实际写出隐式def flatten [T](x:(T,Any)),因为您的错误建议您

这是快速解决方案.它提供了几个警告,但它很好地工作:

implicit def FS[T](x: T): List[T] = List(x)

  implicit def FP[T](x: Product): List[T] = {
    val res = (0 until x.productArity).map(i => x.productElement(i) match {
      case p: Product => FP[T](p)
      case e: T => FS(e)
      case _ => sys.error("incorrect element")
    })
    res.toList.flatten
  }

  implicit def flatten[T](x: (T,Any))(implicit ft: T=>List[T],fp: Product =>List[T]) =
    ft(x._1) ++ (x._2 match {
      case p: Product => fp(p)
      case t: T => ft(t)
    })


  val l = List( (1,4))) )

  scala> l.map(_.flatten)
  res0: List[List[Int]] = List(List(1,List(1,3),4))

UPD
我已经研究了一些问题,并且我找到了简单的解决方案来制作同质列表,这可能在编译时失败.它是完全打字的,没有Any和匹配,看起来编译器现在可以正确解析嵌套的implicits

case class InfiniteTuple[T](head: T,tail: Option[InfiniteTuple[T]] = None) {
    def flatten: List[T] = head +: tail.map(_.flatten).getOrElse(Nil)
  }

  implicit def toInfiniteTuple[T](x: T): InfiniteTuple[T] = InfiniteTuple(x)

  implicit def toInfiniteTuple2[T,V))(implicit ft: V => InfiniteTuple[T]): InfiniteTuple[T] =
    InfiniteTuple(x._1,Some(ft(x._2)))

  def l: List[InfiniteTuple[Int]] = List( (1,4)))) //OK

  def c: List[InfiniteTuple[Int]] = List( (1,"44"))))

  //Compile-time error
  //<console>:11: error: No implicit view available from (Int,(Int,java.lang.String)) => InfiniteTuple[Int]

然后你可以实现你想要的任何压扁.例如,上面一个:

scala> l.map(_.flatten)
res0: List[List[Int]] = List(List(1,4))

(编辑:李大同)

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

    推荐文章
      热点阅读