如何获得隐式转换以在集合内工作? [英] How can I get implicit conversions to work inside collections?

查看:19
本文介绍了如何获得隐式转换以在集合内工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个隐式转换:

隐式定义 aToB(a: A):B={...}

如何让这种隐式转换作用于 List 的元素?

如果我有:

val listOfA: List[A] ...

并且我有一个函数接受 B 的列表,是否可以让 Scala 将所有元素从 A 隐式转换为 B?

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

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

但我希望这能像魔法"一样发生……这要求太多了吧.

解决方案

以下是您可能希望考虑的一些替代方案:

1.使用视图边界

如果可以更改采用 B 列表的函数,这将是最简单的解决方案.修改它以接受可以转换为 Bs 的事物列表.也就是说,

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

会变成

def yourFn[X <% B](l: List[X]) = ...

然后,您可以使用 listOfA 调用该函数:

yourFn(listOfA)

2.介绍一种转换方法

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

def convert[B, A <% B](l: List[A]): List[B] = l map { a =>一:乙}

然后在函数的调用站点,你会写

yourFn(convert(listOfA))

就像 Rogach 的第二个解决方案一样,这比引入隐式转换要安全一些.

3.引入隐式转换

这相当于 Rogach 的第一个解决方案,但符号更好一些(IMO).

implicit def convert[B, A <% B](l: List[A]): List[B] = l map { a =>一:乙}

如果此转换在您的调用站点范围内,您只需使用 listOfA 调用您的函数:

yourFn(listOfA)

离别思绪

考虑如何以一般方式解决这个问题很有趣.如果我想定义我的转换方法以便它可以处理实现 map 方法的任何类型怎么办?即,

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

这当然行不通,因为签名中没有任何内容表示C 必须实现map 的约束.据我所知,表达这个约束是相当复杂的,不能以对任何实现 map 的类型提供开箱即用的支持的方式来完成.请参阅类型安全的 Scala 序列推导.>

Say I have an implicit conversion:

implicit def aToB(a: A):B={
...
}

How can I get this implicit conversion to work on the elements of a List?

If I have:

val listOfA: List[A] ...

and I have a function that takes a List of B, is it possible to let Scala implicitly convert all of the elements from A's to B's?

Without implicit conversions, the conversion might look like:

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

But I would love for this to happen like 'magic'... is that too much to ask.

解决方案

Here are a few alternatives you might wish to consider:

1. Use a view bound

If it's possible to change the function that takes a List of Bs, this would be the simplest solution. Modify it to accept a List of things that can be converted to Bs. That is,

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

would become

def yourFn[X <% B](l: List[X]) = ...

Then, you can just call the function with listOfA:

yourFn(listOfA)

2. Introduce a conversion method

This is similar to Rogach's first solution, except that the outer conversion is non-implicit:

def convert[B, A <% B](l: List[A]): List[B] = l map { a => a: B }

Then at your function's call-site, you would write

yourFn(convert(listOfA))

Like Rogach's second solution, this is bit safer than bringing in an implicit conversion.

3. Introduce an implicit conversion

This is equivalent to Rogach's first solution, but the notation is a bit nicer (IMO).

implicit def convert[B, A <% B](l: List[A]): List[B] = l map { a => a: B }

If this conversion is in scope at your call-site, you can just call your function with the listOfA:

yourFn(listOfA)

Parting Thoughts

It's interesting to consider how to solve this problem in a general way. What if I want to define my conversion method so that it can handle any type that implements the map method? i.e.,

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

This won't work, of course, since nothing in the signature expresses the constraint that C must implement map. As far as I know, expressing this constraint is fairly involved and cannot be done in a way that provides out-of-the-box support for any type that implements map. See Type-safe Scala sequence comprehensions.

这篇关于如何获得隐式转换以在集合内工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆