如何在Scala中概括类型参数

时间:2013-02-13 16:51:21

标签: scala types

我有一个我正在打电话给groupAy的Pairs列表。但是,groupBy在值中包含该对的两个部分,并且我只想包括未按“分组”的那部分。

List(1->2, 1->3, 2->3) groupBy (_._1)
  

scala.collection.immutable.Map [Int,List [(Int,Int)]] = Map(1 - >   列表((1,2),(1,3)),2 - >列表((2,3)))

我写了一个方法来映射Map条目并删除欺骗键:

def removeDupeKeyFromPair[A, B](m: Map[A, List[Pair[A, B]]]): Map[A, List[B]] =
  m map { case(k, vlist) => k -> { vlist map { case(dupe, b) => b } } }

但是,我想从List[Pair[A,B]]C[Pair[A,B]] C<:Iterable来概括这一点,所以我尝试了

def removeDupeKeyFromPair[A, B, C[Pair[A, B]] <: Iterable[Pair[A, B]]]
                         (m: Map[A, C[Pair[A, B]]]): Map[A, C[B]]

但这产生了

  

错误:B没有预期的类型参数:两个

如何正确表达这些类型?

修改 这对我来说是一次学习练习,所以我对如何恰当地表达给定类型比我找到另一种解决方案更感兴趣。虽然了解其他解决方案也很棒。

3 个答案:

答案 0 :(得分:3)

如果您只想更改Map值,可以使用mapValues

scala> List(1->2, 1->3, 2->3) groupBy (_._1) mapValues (_.map(_._2))
res2: scala.collection.immutable.Map[Int,List[Int]] = Map(2 -> List(3), 1 -> List(2, 3))

或者以稍微可读的方式:

scala> List(1->2, 1->3, 2->3) groupBy (_._1) mapValues (lst => lst.map { case(_ ,b) => b })
res3: scala.collection.immutable.Map[Int,List[Int]] = Map(2 -> List(3), 1 -> List(2, 3))

答案 1 :(得分:1)

使用C<:Iterable有什么意义?

如果你定义:

def removeDupeKeyFromPair[A,B](m: Map[A, Iterable[(A,B)]]) : Map[A, Iterable[B]]=
      m map { case(k, vlist) => k -> { vlist map { case(dupe, b) => b } } }

并在列表上调用该方法,它将返回Map[A, List[B]]。这是由于scala集合中的Builder机制。

答案 2 :(得分:1)

为了使这些更通用的东西你可以使用专门的类型类。用于mapflatMap等方法的是FilterMonadic

FilterMonadic将地图方法指定为使用CanBuildFrom。大多数内置集合类都有其中一个可用。然后你可以像这样使用它:

def removeDupeKeyFromPair[A, B, 
  // Define a type C that has type arguments and extends FilterMonadic
  C[X] <: FilterMonadic[X, C[X]], 
  // Define the type that will be returned (provided by the implicit CanBuildFrom)
  That](
    // Use C instead of List    
    m: Map[A, C[(A, B)]])(
      // Define the CanBuildFrom that is required by the map method
      implicit bf:CanBuildFrom[C[(A, B)], B, That]): Map[A, That] =

        // actual logic
        m.map { case (k, vlist) =>
          k -> vlist.map { case (dupe, b) => b }
        }

修改

请注意,我使用的是(A, B)符号,而不是Pair[A, B]