在scala中对集合进行操作的泛型函数

在scala中对集合进行操作的泛型函数,scala,collections,Scala,Collections,这似乎是一个简单的问题,我以前肯定有人问过,但找不到我想要的 如何编写一个函数,将集合作为参数(或任何可以视为集合的对象),对其执行某些操作,并返回相同类型的集合 e、 g: 但当我尝试其他系列(例如,选项)时,令人惊讶: 一个小问题是返回类型Traversable,理想情况下,返回类型应该是给定给方法的任何类型。更大的问题是实际的实现类型:选项变成了列表。 更糟糕的是,在类(行为类似于集合)上尝试,但在其作用域中没有隐式的。e、 g:试试看: scala> import scala.ut

这似乎是一个简单的问题,我以前肯定有人问过,但找不到我想要的

如何编写一个函数,将集合作为参数(或任何可以视为集合的对象),对其执行某些操作,并返回相同类型的集合

e、 g:

但当我尝试其他系列(例如,
选项
)时,令人惊讶:

一个小问题是返回类型
Traversable
,理想情况下,返回类型应该是给定给方法的任何类型。更大的问题是实际的实现类型:
选项
变成了
列表
。 更糟糕的是,在类(行为类似于集合)上尝试,但在其作用域中没有隐式的。e、 g:
试试看

scala> import scala.util._
import scala.util._

scala> foo(Success("HelloWorld"))
<console>:12: error: No implicit view available from scala.util.Success[String] => Traversable[String].
              foo(Success("HelloWorld"))
                 ^

映射的概念由函子表示。为常见类轻松提供函子实现的一种方法是使用scalaz库:

import scala.language.higherKinds
import scalaz.Functor
import scalaz.Scalaz._

def foo[El <: String, Coll[_]](repr: Coll[El])(implicit ev: Functor[Coll]) =
    repr.map(_.size)
将它与
Some
一起使用有点问题,因为只有
选项
具有
Functor
实现,而不是
Some

scala> foo(Some("HelloWorld"))
<console>:12: error: could not find implicit value for parameter ev: scalaz.Functor[Some]
              foo(Some("HelloWorld"))
                 ^
scalaz没有任何用于
Try
的typeclass实现,因此如果您想将
Functor
Try
一起使用,您必须自己提供实现:

import scala.util.Try
import scalaz.Functor

implicit object TryIsFunctor extends Functor[Try] {
  def map[A, B](fa: Try[A])(f: A => B): Try[B] = fa map f
}
然后
foo
将使用
Try
,但类似于
选项
,参数的类型应为
Try
,而不是
Success
Failure

scala> foo(Vector("Hello","World"))
res1: scala.collection.immutable.Vector[Int] = Vector(5, 5)

scala> foo(List("Hello","World"))
res2: List[Int] = List(5, 5)

scala> import scala.concurrent.Future
scala> import scala.concurrent.ExecutionContext.Implicits.global
scala> foo(Future("HelloWorld")) andThen PartialFunction(println(_))

Success(10)
scala> foo(Try("HelloWorld"))
res9: scala.util.Try[Int] = Success(10)
此外,我认为,对于更一般的集合类型,如
Iterable
Seq
,scalaz中没有
Functor
实现

在常见的高阶函数中,
Functor
只支持
map
。因此,要使用
flatMap
filter
必须提供不同的类型类,而不是
Functor
。例如,
scalaz.Monad
支持
map
flatMap
scalaz.MonadPlus
支持
map
flatMap
过滤器


如果您不想使用scalaz,您可能需要自己制作一些与TypeClass非常相似的东西,以获得一个好的结果类型,而不是
可遍历的
。例如,使用标准库中的
CanBuildFrom

映射的概念由函子表示。为常见类轻松提供函子实现的一种方法是使用scalaz库:

import scala.language.higherKinds
import scalaz.Functor
import scalaz.Scalaz._

def foo[El <: String, Coll[_]](repr: Coll[El])(implicit ev: Functor[Coll]) =
    repr.map(_.size)
将它与
Some
一起使用有点问题,因为只有
选项
具有
Functor
实现,而不是
Some

scala> foo(Some("HelloWorld"))
<console>:12: error: could not find implicit value for parameter ev: scalaz.Functor[Some]
              foo(Some("HelloWorld"))
                 ^
scalaz没有任何用于
Try
的typeclass实现,因此如果您想将
Functor
Try
一起使用,您必须自己提供实现:

import scala.util.Try
import scalaz.Functor

implicit object TryIsFunctor extends Functor[Try] {
  def map[A, B](fa: Try[A])(f: A => B): Try[B] = fa map f
}
然后
foo
将使用
Try
,但类似于
选项
,参数的类型应为
Try
,而不是
Success
Failure

scala> foo(Vector("Hello","World"))
res1: scala.collection.immutable.Vector[Int] = Vector(5, 5)

scala> foo(List("Hello","World"))
res2: List[Int] = List(5, 5)

scala> import scala.concurrent.Future
scala> import scala.concurrent.ExecutionContext.Implicits.global
scala> foo(Future("HelloWorld")) andThen PartialFunction(println(_))

Success(10)
scala> foo(Try("HelloWorld"))
res9: scala.util.Try[Int] = Success(10)
此外,我认为,对于更一般的集合类型,如
Iterable
Seq
,scalaz中没有
Functor
实现

在常见的高阶函数中,
Functor
只支持
map
。因此,要使用
flatMap
filter
必须提供不同的类型类,而不是
Functor
。例如,
scalaz.Monad
支持
map
flatMap
scalaz.MonadPlus
支持
map
flatMap
过滤器


如果您不想使用scalaz,您可能需要自己制作一些与TypeClass非常相似的东西,以获得一个好的结果类型,而不是
可遍历的
。例如,使用标准库中的
CanBuildFrom

我确实认为Kolmar在一般问题上是正确的,但Scala确实支持duck类型,因此您可以这样做:

def foo[T[V]](duck: {def map[U](value: String=>U): T[_]}) ={
   duck.map(_.size)
}

foo(Vector("bar")).toVector                         //> res0: Vector[_$2] = List(3)
foo(Some("bar"))                                  //> res1: Option[_$2] = Some(3)

(toVector只是为了强制执行迭代器的求值,否则会产生结果)

我确实认为Kolmar在一般问题上是正确的,但是Scala确实支持duck类型,所以您可以这样做:

def foo[T[V]](duck: {def map[U](value: String=>U): T[_]}) ={
   duck.map(_.size)
}

foo(Vector("bar")).toVector                         //> res0: Vector[_$2] = List(3)
foo(Some("bar"))                                  //> res1: Option[_$2] = Some(3)

(toVector只是为了强制执行迭代器的求值,否则会产生结果)

并非所有集合都可以支持所有可能的操作,因此通常不能编写支持任意操作的内容。您需要的操作类型有什么限制吗?具体来说,我只有一个
map
调用。但是,如果有一种更通用的方法,并且允许其他操作,如
flatMap
filter
,我想知道如何操作。同样,并非所有集合都支持所有操作。因此,您需要以某种方式约束类型。您是否要求能够定义一个操作,该操作适用于(比如)所有支持
flatMap
的集合类型?还是别的什么?换句话说,在“任何可以被看作一个集合”的东西中,你指的是“被当作一个集合”?你认为FO(选项[t])是什么样的实现返回类型?不是所有的集合都支持所有可能的操作,所以一般来说,你不能编写任何东西来支持任意操作。您需要的操作类型有什么限制吗?具体来说,我只有一个
map
调用。但是,如果有一种更通用的方法,并且允许其他操作,如
flatMap
filter
,我想知道如何操作。同样,并非所有集合都支持所有操作。因此,您需要以某种方式约束类型。您是否要求能够定义一个操作,该操作适用于(比如)所有支持
flatMap
的集合类型?或者别的什么?换句话说,你在“任何东西”中“被当作一个集合”是什么意思