如何使这个Scala隐式转换工作?

时间:2011-12-09 01:45:00

标签: scala implicit

我正在使用一个给我以下内容的库(关系可以隐式转换为节点):

class Relation[A,B]
class Node[A,B](r: Relation[A,B])
implicit def relation2node[A,B](r: Relation[A,B]) = new Node(r)

我正在扩展关系以供我自己使用:

class XRelation[A] extends Relation[A,Int]

关系/ XRelations应该是子类:

class User extends XRelation[Int]

现在,我还定义了自己的Helper方法,如GET,旨在与任何Node和任何转换为​​Node的东西一起使用:

class Helper[A,B](n: Node[A,B]) { def GET {} }

// note: this is the only way I know of to make the next example work.
implicit def xx2node2helper[A,B,C[_,_]](x: C[A,B])(implicit f: C[A,B] => Node[A,B]) = new Helper(x)

所以这个例子有效:

new Relation[Int,Int]().GET

如果我添加另一个隐式转换:

// don't understand why this doesn't work for the previous example
// but works for the next example
implicit def x2node2helper[A,B,C](x: C)(implicit f: C => Node[A,B]) = new Helper(x)

我也可以进行以下转换工作:

new XRelation[Int]().GET

但这不起作用:

new User().GET

可悲的是,这失败了:

error: No implicit view available from Sandbox3.User => Sandbox3.Node[A,B]

任何人都可以理解这一切并解释如何让最后一个例子起作用吗?提前谢谢。

更新:我知道你可以从Relation引入隐式转换,但我要求(1)弄清楚如何做到这一点,而不必引入每个单词的含义可能隐式转换为Node的类型,以及(2)巩固我对implicits的理解。

2 个答案:

答案 0 :(得分:4)

implicit def nodeLike2Helper[R, C <: R](r:C)(implicit f: R => Node[_,_]) = {
  new Helper(r)
}

正如错误消息所示,User没有隐式转换为Node。但它是超级超级联盟。所以你只需给出正确的界限来输入参数。

仅供参考,视图边界有一个语法糖<%,因此上面的代码可以更短:

implicit def nodeLike2Helper[R <% Node[_,_], C <: R](r:C) = {
  new Helper(r)
}

答案 1 :(得分:1)

在检查User是否与类型模式C[_,_]匹配时,scala解析只会深入一个超类。您可以通过取消以下代码中的模式来解决此问题。

implicit def x2node2helper[A,B](x: Relation[A,B])(implicit f: Relation[A,B] => Node[A,B]) = new Helper(x)

如果隐式relation2node在x2node2helper定义的范围内,则可以编写

implicit def x2node2helper[A,B](x: Relation[A,B]) = new Helper(x)