如何在Scala中泛化类型参数

如何在Scala中泛化类型参数,scala,types,Scala,Types,我有一个我称之为groupBy的配对列表。但是,groupBy在值中包含了该对的两个部分,我只想包含该对中没有“分组依据”的部分 scala.collection.immutable.Map[Int,List[(Int,Int)]]=Map(1-> 列表((1,2)、(1,3)),2->List((2,3))) 我编写了一个方法来映射映射条目并删除复制键: def removeDupeKeyFromPair[A, B](m: Map[A, List[Pair[A, B]]]): Map[A, L

我有一个我称之为groupBy的配对列表。但是,groupBy在值中包含了该对的两个部分,我只想包含该对中没有“分组依据”的部分

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

我编写了一个方法来映射映射条目并删除复制键:

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如果您只想更改
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))

如果您只想更改
映射
值,可以使用
映射值

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))

使用
C有什么意义?使用
C有什么意义?为了使这些东西更通用,您可以使用专门的类型类。用于
map
flatMap
等方法的是
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 }
        }
def从对[A,B,
//定义具有类型参数并扩展FilterMonadic的类型C
C[X]
k->vlist.map{case(dupe,b)=>b}
}
编辑
请注意,我使用了
(A,B)
符号,而不是
对[A,B]
,为了使这些东西更通用,您可以使用专门的类型类。用于
map
flatMap
等方法的是
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 }
        }
def从对[A,B,
//定义具有类型参数并扩展FilterMonadic的类型C
C[X]
k->vlist.map{case(dupe,b)=>b}
}
编辑
注意,我使用了
(A,B)
符号,而不是
对[A,B]

这非常有用,感谢您向我介绍mapValues。它看起来与我在上面编写的map语句相同,忽略了键和列表值的映射。如果要将传递给mapValues的匿名函数改为命名函数,您将如何表示类型参数?这非常有用,感谢您向我介绍mapValues。它看起来相当于我上面写的map语句,忽略了键和列表值上的映射。如果您要编写作为命名函数传递给mapValues的匿名函数,您将如何表示类型参数?原因是(无可否认的混淆)诊断是要求
C
获取
对[a,B]
类型参数,然后引用
C[B]
,这会导致编译器看到
C[B]的参数位置中的形式
B
(本身不是类型构造函数)和对
B
的引用不一致
。如果这一点很清楚的话……C是一个正式的泛型参数,一个包含任何东西的泛型容器:`C[X]诊断的原因(无可否认是令人困惑的)是您需要
C
获取一个
对[a,B]
类型参数,然后参考
C[B]
,这会导致编译器看到形式的
B
(本身不是类型构造函数)和
C[B]
的参数位置中对
B
的引用之间不一致。如果这很清楚的话……C是一个形式的泛型参数,任何东西的泛型容器:`C[X]