Это не работает, потому что спецификация языка Scala определяет представление следующим образом:
Неявные параметры и методы также могут определять неявные преобразования, называемые views . Вид типа S для ввода T определяется неявным значением, имеющим тип функции S => T или (=> S) => T или методом, конвертируемым в значение этого типа.
blockquote>
fromOptionToOption
не соответствует трем категориям, так как он принимает неявный параметр. Компилятор, похоже, не находит конвертер с назначением и источником, имеющим общий тип.Определение представления с
Option[Foo]
доOption[Bar]
работает как ожидалось.trait T case class Foo(i: Int) extends T case class Bar(i: Int) extends T object Main { implicit def fromFooToBar(f: Foo):Bar = Bar(f.i) implicit def fromBarToFoo(b: Bar):Foo = Foo(b.i) // implicit def fromOptionToOption[A, B](from: Option[A])(implicit conversion: (A) => B): Option[B] = // from.map(conversion(_)) implicit def fromOptionFooToOptionBar(o: Option[Foo]): Option[Bar] = o map { foo => foo } def test(): Option[Bar] = { val fooOpt = Some(Foo(4)) val barOpt2: Option[Bar] = fooOpt barOpt2 } } println(Main.test)
Выполнение этого вывода:
$ scala so.scala Some(Bar(4))
Однако все не теряется. Это не так хорошо, как общий
Option
доOption
, но мы можем сделать что-то вроде того, что может превратиться вBar
вOption[Bar]
по просмотру.trait T case class Foo(i: Int) extends T case class Bar(i: Int) extends T object Main { implicit def fromFooToBar(f: Foo):Bar = Bar(f.i) implicit def fromBarToFoo(b: Bar):Foo = Foo(b.i) implicit def fromOptionToOptionBar[A <% Bar](from: Option[A]): Option[Bar] = from map { foo => foo } def test(): Option[Bar] = { val fooOpt = Some(Foo(4)) val barOpt2: Option[Bar] = fooOpt barOpt2 } } println(Main.test)
Вот еще одно обходное решение, которое может использоваться для общих
Option
-Option
, но требует дополнительного вызова.convert
:trait T case class Foo(i: Int) extends T case class Bar(i: Int) extends T case class Converter[A](x: Option[A]) { def convert[B](implicit ev: Function1[A, B]): Option[B] = x map { a: A => ev(a) } } object Main { implicit def optionToConverter[A](x: Option[A]) = Converter(x) implicit def fooToBar(x: Foo) = Bar(x.i) def test(): Option[Bar] = { val fooOpt = Some(Foo(4)) val barOpt: Option[Bar] = fooOpt.convert barOpt } } println(Main.test)