Как я могу обойти это ограничение разрешения перегрузки в Scala? - PullRequest
4 голосов
/ 03 октября 2010

В Scala взаимодействие перегрузки и неявного разрешения аргументов, по-видимому, делает невозможным использование следующего кода.

trait Bijection[A, B] extends Function1[A, B] with Unapply[A, B] { self =>
  def apply(a: A): B
  def unapply(b: B): A
}

sealed trait Unapply[A, B] {
  def unapply(b: B): A
}

object Bijection {
  implicit def biject[A](a: A): Biject[A] = new Biject(a)

  implicit object IntStringBijection extends Bijection[Int, String] {
    override def apply(a: Int): String = a.toString
    override def unapply(b: String): Int = b.toInt
  }
}

sealed class Biject[A](a: A) {
  def as[B](implicit f: Function1[A, B]): B = f(a)
  def as[B](implicit f: Unapply[B, A]): B = f unapply a
}

Здесь цель состоит в том, чтобы a.as [B] выполнить типобезопасное преобразование независимо от того, доступны ли Bijection [A, B] или Bijection [B, A] в неявном объеме.

Причина, по которой это не работает, заключается в том, что неявное разрешение, по-видимому, имеет место после устранения неоднозначности перегрузки в компиляторе, и, поскольку обе реализации 'as' имеют одинаковый тип результата, компилятор даже не доходит до попытки выяснить, находится ли в области видимости неявный, который может выполнить преобразование. Короче говоря, неявное разрешение не используется при устранении неоднозначности перегрузки.

Причина, по которой я хочу, чтобы «as» была перегружена, состоит в том, чтобы избежать необходимости для пользователя этой библиотеки кодировать «направление» биекции в месте вызова; очевидно, можно реализовать Biject следующим образом:

sealed class Biject[A](a: A) {
  def viaForward[B](implicit f: Function1[A, B]): B = f(a)
  def viaReverse[B](implicit f: Unapply[B, A]): B = f unapply a
}

но это действительно непривлекательно, потому что это делает сутенера лишним; с тем же успехом можно явно пропустить биекцию, но тогда, конечно, вы потеряете возможность изменять используемую биекцию в зависимости от объема.

Есть ли хорошее решение этой проблемы?

1 Ответ

5 голосов
/ 03 октября 2010

Как это?

trait Bijection[A, B] extends Function1[A, B] with Unapply[A, B] {
  self =>
  def apply(a: A): B

  def unapply(b: B): A
}

sealed trait Unapply[A, B] {
  def unapply(b: B): A
}

object Bijection {
  implicit def biject[A](a: A): Biject[A] = new Biject(a)

  implicit object IntStringBijection extends Bijection[Int, String] {
    override def apply(a: Int): String = a.toString

    override def unapply(b: String): Int = b.toInt
  }
}

sealed class Biject[A](a: A) {
  def as[B](implicit f: Either[Bijection[A, B], Bijection[B, A]]): B = f.fold(_ apply a, _ unapply a)
}

trait EitherLow {
  implicit def left[A, B](implicit a: A): Either[A, B] = Left(a)
}

object Either extends EitherLow {
  implicit def right[A, B](implicit b: B): Either[A, B] = Right(b)
}

import Bijection._
import Either._

1.as[String]
"1".as[Int]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...