Строка сопутствующий объект в Scala

Учитывая тип, который имеет "конвертер", я хотел бы иметь автоматическое преобразование при вызове метода с использованием объекта-компаньона этого типа. То есть, учитывая следующее определение,

case class Converted(name: String)

trait Converter[A] {
  def perform: Converted
}

implicit val StringConverter = new Converter[String] {
  def perform = Converted("String")
}

заставить следующий код работать:

implicit def toConverter(a: String.type): Converted = 
  implicitly[Converter[String]].perform // Error: `Found String.type, required AnyRef`

def f(needsConverted: Converted) = ???

f(String) // <- That's what I would like to be able to write.

Но это терпит неудачу, и обе попытки преобразования терпят неудачу. Обратите внимание, что я не могу изменить f потому что он предоставляется сторонней библиотекой и их много.

  1. Могу я сделать f(String) компилировать с использованием имплицитов?

Если это невозможно для строк, как насчет классов, у которых есть объект-компаньон, могу ли я сделать это в общем случае так:

object TheClass

case class TheClass()

implicit val TheClassConverter = new Converter[TheClass] {
  def perform = Converted("TheClass")
}

implicit def toConverter[A: Converter](a: A.type): Converted =
  implicitly[Converter[A]].perform // Error: `Not found value A`

implicit def toConverter(a: TheClass.type): Converted = 
  implicitly[Converter[TheClass]].perform // This works but is not generic

f(TheClass) // This works.
  1. Могу ли я сделать первый toConverter Скомпилировать?

3 ответа

Решение

Вместо определения неявного экземпляра для типа MyClass Вы можете определить неявный экземпляр для типа компаньона MyClass.type,

implicit val TheClassConverter: Converter[MyClass.type] = new Converted[MyClass.type] {
  def perform = Converted("MyClass")
}

Можно ли сделать компиляцию f(String) с использованием имплицитов?

Нет. Вы можете определить значение под названием Stringконечно, но это не будет связано с типом String,

implicit toConverter[A: Converter](a: A.type): Converted =
    implicitly[Converter[A]].perform

A в A.type должно быть значением; это не связано с параметром типа A,

На самом деле, что касается системы типов Scala, нет никакой связи между классом / признаком и его сопутствующим объектом. Таким образом, вы не можете делать то, что вы хотите в общем.

Конечно, если вы не настаиваете на использовании () вместо []становится тривиально

def f1[A: Converter] = f(implicitly[Converter[A]].perform)

f1[String]
f1[TheClass]

Не уверен, что вы пытаетесь сделать, но следующие работы для меня

case class Converted(name: String)

trait Converter[A] {
  def perform: Converted
}

implicit def toConverted(name: String) = Converted("String")
implicit def toIntConverted(int: Int) = Converted("Int")

def f(needsConverted: Converted): String = needsConverted.name

f("some")
f(5)
Другие вопросы по тегам