Почему 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: Я намерен передать фабрике «Attr», производящей «Attributes», тип значения «String», а также имя «foo» для всех атрибутов, которые она когда-либо создавала.

Строка 2: Используя ранее настроенную фабрику атрибутов, я фактически создаю атрибут с именем «foo» со значением «bar» типа «String».

Мой вывод: поскольку параметризованным типом «A» для этого фабричного объекта является «String», компилятор Scala выводит те же сигнатуры параметров метода «apply» being «(value: String)», которые неоднозначны. Поэтому я попытался изменить сигнатуру, добавив неявный список параметров.

Прочитав статью о type erasure и 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")

Кажется, я думал слишком сложно. Вместо того, чтобы перегрузить метод apply списком параметров (value: String), я просто избавился от него. Версия, которая полностью оправдывает мои ожидания, теперь выглядит так:

final case class Attr[A](name: String)(implicit conv: String To A) {
  def apply(value: A) = Attribute(name, value)
}

person Tim Friske    schedule 22.08.2011    source источник
comment
Не могли бы вы опубликовать сокращенный, автономный образец кода, который показывает получаемое вами сообщение об ошибке? Я не совсем понимаю твои намерения.   -  person Kipton Barros    schedule 23.08.2011
comment
Также: в ответе на вопрос о переполнении стека, который вы связали, ретроним утверждает: Пожалуйста, рассматривайте это как возможность узнать о стирании, границах контекста и неявном поиске, а не как шаблон, который будет применяться в реальном коде! Может быть, есть более простой способ добиться того, что вам нужно.   -  person Kipton Barros    schedule 23.08.2011
comment
Я обновил статью, чтобы прояснить свои намерения и выводы.   -  person Tim Friske    schedule 23.08.2011


Ответы (1)


Как насчет этого?

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 примет любое значение типа B, которое может быть преобразовано в A == String, включая сами строки (в этом случае используется неявное преобразование Predef.conforms).

person Kipton Barros    schedule 23.08.2011
comment
Прежде всего, большое спасибо за ваш ответ. Хотя я хотел бы увидеть мой пример кода, приведенный в исходной публикации, меня больше всего интересует вопрос, почему компилятор Scala не имеет значения, когда он находит второй список параметров, который является неявным, и найдено значение типа DummyImplicit в Predef. - person Tim Friske; 23.08.2011
comment
Теперь по поводу вашего предложения: к сожалению, AttrBuilder носит слишком общий характер. Параметризуя его с помощью типа String, его apply метод должен принимать либо значения типа источника String, преобразовывая данное значение в тип цели A, либо сразу же принимать значение типа цели A. - person Tim Friske; 23.08.2011
comment
Я нашел решение, удовлетворяющее моим требованиям. Смотрите конец моего оригинального поста. - person Tim Friske; 24.08.2011