Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 如何使隐式转换在集合内工作?_Scala - Fatal编程技术网

Scala 如何使隐式转换在集合内工作?

Scala 如何使隐式转换在集合内工作?,scala,Scala,假设我有一个隐式转换: implicit def aToB(a: A):B={ ... } 如何使这种隐式转换在列表的元素上工作 如果我有: val listOfA: List[A] ... 我有一个函数,它接受B的列表,可以让Scala隐式地将所有元素从a转换为B吗 如果没有隐式转换,转换可能如下所示: lisftOfA.map(a => new B(a.someValue, a.anotherValue)) 但我希望这能像“魔法”一样发生。。。这是不是要求太多了。以下是一个通用解

假设我有一个隐式转换:

implicit def aToB(a: A):B={
...
}
如何使这种隐式转换在列表的元素上工作

如果我有:

val listOfA: List[A] ...
我有一个函数,它接受B的列表,可以让Scala隐式地将所有元素从a转换为B吗

如果没有隐式转换,转换可能如下所示:

lisftOfA.map(a => new B(a.someValue, a.anotherValue))

但我希望这能像“魔法”一样发生。。。这是不是要求太多了。

以下是一个通用解决方案,如果范围内存在隐式转换a=>B,则可以实现列表的隐式转换(列表[a]=>列表[B]):

scala> class A
defined class A

scala> class B
defined class B

scala> implicit def a2b(a:A) = new B
a2b: (a: A)B

scala> implicit def mapI[A,B](l: List[A])(implicit conv: A => B): List[B] = l.map(conv)
mapI: [A, B](l: List[A])(implicit conv: (A) => B)List[B]

scala> List(new A): List[B]
res0: List[B] = List(B@efa0bf4)
这是你需要的吗

此外,由于您已经进行了隐式转换,您可以只编写:

listOfA.map(a2b) // List[B]

它会更详细一点,但会让您更明确地控制代码。

我认为最好的方法是

implicit def asToBs(as: List[A]): List[B] = as map aToB

以下是您可能希望考虑的几个备选方案:

1。使用视图绑定

如果有可能更改接受一个Bs列表的函数,这将是最简单的解决方案。修改它以接受可以转换为Bs的事物列表。就是

def yourFn(l: List[B]) = ...
将成为

def yourFn[X <% B](l: List[X]) = ...
2。介绍一种转换方法

这与Rogach的第一个解决方案类似,只是外部转换是非隐式的:

def convert[B, A <% B](l: List[A]): List[B] = l map { a => a: B }
与Rogach的第二个解决方案一样,这比引入隐式转换要安全一些

3。引入隐式转换

这相当于Rogach的第一个解决方案,但表示法稍微好一点(IMO)

离别的思念

考虑如何用一般的方法来解决这个问题很有趣。如果我想定义转换方法,以便它能够处理实现
map
方法的任何类型,该怎么办?i、 e

def convert[B, A <% B, C[_]](c: C[A]): C[B] = c map { a => a: B }
def convert[B,A:B}

当然,这是行不通的,因为签名中没有任何内容表示
C
必须实现
map
的约束。据我所知,表示此约束相当复杂,不能以一种为实现
map
的任何类型提供开箱即用支持的方式完成。请参阅。

完整性,请参阅可能会考虑采用更一般的方法.

该计划:

import scala.collection.generic.CanBuildFrom
import scala.language.{higherKinds, implicitConversions}

implicit def implyConvertedTraversable[A, B, C[X] <: Traversable[X]](as: C[A])(implicit conversion: A => B, cbf: CanBuildFrom[C[A], B, C[B]]): C[B] = {
  val builder = cbf(as)
  builder.sizeHint(as)
  builder ++= as.map(conversion)
  builder.result()
}

implicit def implyString(a: Int): String = a.toString

val intList = List(1, 2, 3)
val intStream = Stream(1, 2, 3)

val stringList: List[String] = intList
val stringStream: Stream[String] = intStream

你确定,类型擦除不会有问题吗?@om nom nom-为什么会有问题?隐式在类型擦除之前就解决了。+1我没有遵循这种方法,但这是一个令人耳目一新的简单答案,谢谢。它不起作用。显然列表协方差会混淆编译器。请检查PleaseThaks以获得伟大的示例和解释。首先,我想知道如何在映射中“类型强制转换”,即a=>a:B。有这样做的名称吗?它被称为类型归属。您将类型
B
归因于类型
a
的对象。这与强制转换不同,强制转换使用Scala中的
作为
方法的安装,因为它在编译时被检查,并且永远不能重新启动运行时异常。这似乎不是@JacobusR所要求的。我们希望转换在
map
函数中工作,该函数是
listOfA
的一个函数。您已经引入了
yourFn
,OP没有提到,但我们需要
listOfA.map((b:b)=>…)
convert一样运行(listOfA.map((b:b)=>…)
。似乎只有在我们定义了
defyourfn[T](listOfB:List[b),fn:b=>T):List[T]=listOfB.map(fn)时,您的解决方案才会起作用
。也就是说,如果我们包装
map
只是为了帮助进行类型推断,这不是我们想要做的。@silasdavis听起来你的问题与OP不同。@JacobusR有一个
List[a]
和一个函数,该函数需要一个
List[B]
,他想应用到他的
List[a]
--我将此函数命名为
yourFn
,但是OP在他的问题中引入了它。这是否已成功测试?在中,我显示3.(隐式转换)实际上不起作用。如果可能,请看一看:)这实际上不起作用:val list=list(新a)val listB:list[B]=列表//未编译。请检查
implicit def convert[B, A <% B](l: List[A]): List[B] = l map { a => a: B }
yourFn(listOfA)
def convert[B, A <% B, C[_]](c: C[A]): C[B] = c map { a => a: B }
import scala.collection.generic.CanBuildFrom
import scala.language.{higherKinds, implicitConversions}

implicit def implyConvertedTraversable[A, B, C[X] <: Traversable[X]](as: C[A])(implicit conversion: A => B, cbf: CanBuildFrom[C[A], B, C[B]]): C[B] = {
  val builder = cbf(as)
  builder.sizeHint(as)
  builder ++= as.map(conversion)
  builder.result()
}

implicit def implyString(a: Int): String = a.toString

val intList = List(1, 2, 3)
val intStream = Stream(1, 2, 3)

val stringList: List[String] = intList
val stringStream: Stream[String] = intStream
intList: List[Int] = List(1, 2, 3)
intStream: scala.collection.immutable.Stream[Int] = Stream(1, ?)

stringList: List[String] = List(1, 2, 3)
stringStream: Stream[String] = Stream(1, ?)