为什么 DummyImplicit 没有消除 [String](a: A) 和 (a: String) 的歧义

发布于 2024-11-30 21:08:46 字数 1381 浏览 4 评论 0原文

给出以下代码:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

失眠症患者 2024-12-07 21:08:46

这个怎么样?

case class Attribute[A](name: String, value: A)

case class AttrBuilder[A](name: String)(implicit conv: String => A) {
  def apply[B](value: B)(implicit conv: B => A) = Attribute(name, conv(value))
}

val bldr = new AttrBuilder[String]("MyAttrs")

bldr("hello") // Attribute(MyAttrs, hello)

implicit def int2string(x: Int) = x.toString
bldr(2)       // Attribute(MyAttrs, 2), using int2string implicit

bldr(false)   // fails; cannot find implicit Boolean => String

属性构建器 bldr 将采用任何可转换为 A == StringB 类型值,包括字符串本身(隐式转换 在这种情况下使用 Predef.conforms)。

How about this?

case class Attribute[A](name: String, value: A)

case class AttrBuilder[A](name: String)(implicit conv: String => A) {
  def apply[B](value: B)(implicit conv: B => A) = Attribute(name, conv(value))
}

val bldr = new AttrBuilder[String]("MyAttrs")

bldr("hello") // Attribute(MyAttrs, hello)

implicit def int2string(x: Int) = x.toString
bldr(2)       // Attribute(MyAttrs, 2), using int2string implicit

bldr(false)   // fails; cannot find implicit Boolean => String

The attribute builder bldr will take any value of type B that's convertable to A == String, including strings themselves (the implicit conversion Predef.conforms is used in that case).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文