【问题标题】:how to reparameterize collection type如何重新参数化集合类型
【发布时间】:2015-12-06 01:28:51
【问题描述】:

我想定义一个泛型集合的转换。

def transform[S<:GenIterable[T],T](s:S):S = s.zipWithIndex

这会抛出:

type mismatch; found : scala.collection.GenIterable[(T, Int)] required: S

我必须在函数定义中将S 声明为参数化的GenIterable。我想指定一个输出类型“无论创建 S 的集合类型是什么,除了用 [(T,Int)] 参数化”,这样我就可以保证得到相同的集合类型,而不仅仅是 GenIterable .

我怎样才能做到这一点?

【问题讨论】:

    标签: scala scala-collections implicit generic-programming implicit-typing


    【解决方案1】:

    这是我的存根:

    def transform[S[T]<: GenIterableLike[T,S[T]],T](s:S[T])
      (implicit bf:CanBuildFrom[S[T],(T,Int),S[(T,Int)]]):S[(T,Int)] = {
    
      s.zipWithIndex
    }
    

    签名很糟糕,可以通过将T 替换为_ 来简化(或模糊)。

    试一试:

    scala> val m = Map("x"->"1","y"->"2")
    m: scala.collection.Map[String,String] = Map(x -> 1, y -> 2)
    
    scala> transform(m)
    res3: Iterable[((String, String), Int)] = List(((x,1),0), ((y,2),1))
    
    scala> val s = Set("x", "y")
    s: scala.collection.Set[String] = Set(x, y)
    
    scala> transform(s)
    res4: scala.collection.Set[(String, Int)] = Set((x,0), (y,1))
    
    scala> val seq = List("x", "y")
    seq: List[String] = List(x, y)
    
    scala> transform(seq)
    res5: List[(String, Int)] = List((x,0), (y,1))
    

    关键是使用Like trait,因为它带有正在使用的集合的类型。然后,隐式转换负责其余的工作。请注意,Map 的处理方式。似乎隐式转换默认为将Iterable 转换为List,这是有道理的。

    【讨论】:

    • Yo dawg,升级它的方法!
    猜你喜欢
    • 2022-12-03
    • 2015-12-07
    • 1970-01-01
    • 2012-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-14
    • 2022-01-17
    相关资源
    最近更新 更多