为什么 DummyImplicit 没有消除 [String](a: A) 和 (a: String) 的歧义
给出以下代码:
final case class Attr[A](name: String)(implicit conv: String To A) {
def apply(value: A)(implicit dummy: DummyImplicit) = Attribute(name, value)
def apply(value: String) = Attribute[A](name, value)
}
当 Scala 编译器看到以下值时,它会抱怨“对重载定义的引用不明确”: 第
1| val FooAttr = Attr[String]("foo")
2| val catch22 = FooAttr("bar")
1 行:我的意图是将值类型“String”传递给工厂“Attr”,生成“Attributes” ” 以及它生成的所有属性的名称“foo”。
第 2 行:使用之前配置的属性工厂,我实际上生成了一个名为“foo”的属性,其值为“String”类型的“bar”。
我的结论:因为该工厂对象的参数化类型“A”是“String”,所以 Scala 编译器推导出方法“apply”的相同参数签名是“(value: String)”,这是不明确的。因此,我尝试通过添加隐式参数列表来改变签名。
阅读有关 的文章后类型擦除和 DummyImplicit 并查阅 Scala 参考部分“7.2 隐式参数”我认为“(implicit dummy: DummyImplicit)”会做技巧。
目前我的解决方案是使用最小的包装器:
final case class Txt(str: String) {
override def toString = str
}
鉴于可以找到“Str To Txt”类型的隐式值(即合适的转换函数),上面的第二行将进行编译,即:
2| val catch22 = FooAttr("bar")
看来我也在想复杂的。我只是摆脱了它,而不是使用 (value: String)
参数列表重载 apply
方法。符合我全部期望的版本现在看起来像:
final case class Attr[A](name: String)(implicit conv: String To A) {
def apply(value: A) = Attribute(name, value)
}
Given the following piece of code:
final case class Attr[A](name: String)(implicit conv: String To A) {
def apply(value: A)(implicit dummy: DummyImplicit) = Attribute(name, value)
def apply(value: String) = Attribute[A](name, value)
}
The Scala compiler complains with "ambiguous reference to overloaded definition" when it sees the values hereafter:
1| val FooAttr = Attr[String]("foo")
2| val catch22 = FooAttr("bar")
Line 1: My intent is it to pass to the factory "Attr" producing "Attributes" the value type "String" as well as the name "foo" for all the attributes it ever produces.
Line 2: Using the previously configured attribute factory I am actually producing an attribute named "foo" with the value "bar" of type "String".
My conclusion: Because the parameterized type "A" for this factory object is "String" the Scala compiler deduces the same parameter signatures of method "apply" being "(value: String)" which are ambiguous. Therefore I tried to make a difference in signature by adding an implicit parameter list.
After having read an article about type erasure and DummyImplicit and consulting the Scala reference section "7.2 Implicit parameters" I thought "(implicit dummy: DummyImplicit)" would do the trick.
For the moment my solution is to have the minimal wrapper:
final case class Txt(str: String) {
override def toString = str
}
Given that an implicit value of type "Str To Txt", i.e. a suitable conversion function, could be found, the second line from above compiles, i.e.:
2| val catch22 = FooAttr("bar")
It seems I was thinking too complicated. Instead to overload the apply
method with a parameter list of (value: String)
, I simply got rid of it. The version that lives up to my full expectations now looks like:
final case class Attr[A](name: String)(implicit conv: String To A) {
def apply(value: A) = Attribute(name, value)
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这个怎么样?
属性构建器
bldr
将采用任何可转换为A == String
的B
类型值,包括字符串本身(隐式转换在这种情况下使用 Predef.conforms
)。How about this?
The attribute builder
bldr
will take any value of typeB
that's convertable toA == String
, including strings themselves (the implicit conversionPredef.conforms
is used in that case).