说我List
的{{1}}
Int
当然,Scala非常聪明,可以为我返回正确的类型。现在,考虑到,我对scala> val list = List(1, 2, 3, 4, 5)
list: List[Int] = List(1, 2, 3, 4, 5)
的具体功能不感兴趣,而是想要更通用(超级)类型,比如List
。显然,我可以指定它:
Traversable
但这意味着我还必须重复类型参数。
这不起作用
scala> val trav = list: Traversable[Int]
trav: Traversable[Int] = List(1, 2, 3, 4, 5)
这两个例子完全删除了类型参数信息
scala> list : Traversable
<console>:9: error: type Traversable takes type parameters
list : Traversable
^
有没有办法获得scala> list : Traversable[T forSome {type T}]
res2: Traversable[T forSome { type T }] = List(1, 2, 3, 4, 5)
scala> list : Traversable[_]
res3: Traversable[Any] = List(1, 2, 3, 4, 5)
而无需输入Traversable[Int]
?
答案 0 :(得分:4)
你要求的基本上是多态函数;或者是高等级类型的函数。您可以在类型之间定义这样的映射* - &gt; *如下:
scala> trait ~>[F[_], G[_]] { def map[A](f: F[A]): G[A] }
defined trait $tilde$greater
你需要一个隐含的课程
scala> implicit object ListIsTrav extends (List ~> Traversable) {
| def map[A](l: List[A]): Traversable[A] = l
| }
defined module ListIsTrav
现在为* - &gt;形式的类型添加转换器*
scala> class Homomorphic[F[_], A](f: F[A]){
| def as[G[_]](implicit ev: F ~> G): G[A] = ev map f
| }
defined class Homomorphic
scala> implicit def Type_Is_Homomorphic[F[_], A](f: F[A]) = new Homomorphic(f)
Type_Is_Homomorphic: [F[_], A](f: F[A])Homomorphic[F,A]
现在使用它:
scala> List(1, 2, 3).as[Traversable]
res0: Traversable[Int] = List(1, 2, 3)
这里的痛苦是List ~> Traversable
排序的隐式实例的指数级爆炸。它在实践中并不可用。
答案 1 :(得分:2)
这有效,但是要避免输入Int有很多工作......也许有人可以基于此提出一个更简洁的技巧。
scala> def traversableId[T](t: Traversable[T])= t
traversableId: [T](t: Traversable[T])Traversable[T]
scala> traversableId(list)
res1: Traversable[Int] = List(1, 2, 3, 4, 5)
答案 2 :(得分:1)
虽然oxbow_lakes给出了关于如何针对任意组合解决此问题的great solution,但他鼓励我如何在Traversable
是List
的超类型的情况下执行此操作1}}。 (但最初并未在问题中指明。)
class CastToSuperType[F[_], A](f: F[A]) {
def as[G[_]](implicit ev: F[A] <:< G[A]): G[A] = f: G[A]
}
implicit def implCastToSuperType[F[_], A](f: F[A]) = new CastToSuperType(f)
scala> List(1, 2, 3).as[Traversable]
res0: Traversable[Int] = List(1, 2, 3)
我怀疑,具有任意数量类型参数的类型可能需要键入lambdas。
答案 3 :(得分:0)
写一个相应的方法:
def asTraversable[T](x: Traversable[T]) = x
asTraversable(x)
答案 4 :(得分:0)
集合类具有大多数广义特征的转换方法
scala> List(1,2,3).toTraversable
res0: Traversable[Int] = List(1, 2, 3)
scala> List(1,2,3).toIterable
res1: Iterable[Int] = List(1, 2, 3)
scala> List(1,2,3).toIndexedSeq
res2: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3)
答案 5 :(得分:0)
在scala 2.10中它更加简单,因为引入了.to[Col[_]]
,它是scala.collection.TraversableLike的一部分
这是定义:
def to[Col[_]](implicit cbf : scala.collection.generic.CanBuildFrom[scala.Nothing, A, Col[A]]) : Col[A]
所以你基本上可以这样做:
scala> List(1, 2, 3, 4, 5).to[Vector]
res0: Vector[Int] = Vector(1, 2, 3, 4, 5)
scala> List(1, 2, 3, 4, 5).to[Set]
res1: Set[Int] = Set(5, 1, 2, 3, 4)