scala中使用扁平元组的高阶运算
我最近遇到了一个问题.我试图以编译器友好的方式压扁“尾嵌套”元组,我想出了下面的代码:
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 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)) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |