как сделать неявное преобразование типов, используемых в моем интерпретаторе

Я пишу интерпретатор и пробовал использовать решение из how-to-set-up-implicit-conversion-to-allow-arithmetic-between-numeric-types для той же проблемы. Мне нужно добавить логическое + логическое значение, Int + логическое значение. , Boolean + Int, Int + Double, Double + Double и т. Д.

Поэтому я использовал классы WeakConformance и C из этого решения.

sealed trait WeakConformance[A <: AnyVal, B <: AnyVal, C] {
  implicit def aToC(a: A): C

  implicit def bToC(b: B): C
}

object WeakConformance {
  implicit def SameSame[T <: AnyVal]: WeakConformance[T, T, T] = new WeakConformance[T, T, T] {
    implicit def aToC(a: T): T = a

    implicit def bToC(b: T): T = b
  }

  implicit def IntDouble: WeakConformance[Int, Double, Double] = new WeakConformance[Int, Double, Double] {
    implicit def aToC(a: Int) = a

    implicit def bToC(b: Double) = b
  }

  implicit def DoubleInt: WeakConformance[Double, Int, Double] = new WeakConformance[Double, Int, Double] {
    implicit def aToC(a: Double) = a

        implicit def bToC(b: Int) = b
      }
   }  

   case class C[A <: AnyVal](val value:A) {
          import WeakConformance.unify
          def +[B <: AnyVal, WeakLub <: AnyVal](that:C[B])(implicit wc: WeakConformance[A, B, WeakLub], num: Numeric[WeakLub]): C[WeakLub] = {  
        new C[WeakLub](num.plus(wc.aToC(x), wc.bToC(y)))
      }
    }

а вот часть моего переводчика

class Interpreter {

......

  def eval(e: Expression): Any = e match {
  ...

    case ADD(lhs, rhs) => (eval(lhs), eval(rhs)) match {

      case (l: C[_], r: C[_]) => l + r  // error comes here

      case _ => error("...")
    }
  }

}

ошибка такая

ошибка: неоднозначные неявные значения: // показывает 2 последних объекта, объявленных как неявные в признаке Numeric, здесь соответствуют ожидаемому типу Numeric[WeakLub]

есть идеи, как заставить его работать? Я хотел, чтобы метод eval возвращал C, но поскольку C[Int] не является экземпляром C[Any], это не решает мою проблему


person Tala    schedule 23.06.2010    source источник


Ответы (1)


Из-за стирания типа вы не можете получить во время выполнения параметр типа C. Вам нужно будет использовать манифесты для хранения этой информации. См. Вопросы, связанные со стиранием манифеста и типа.

person Daniel C. Sobral    schedule 23.06.2010
comment
Да, я знаю о манифестах. Я просто надеялся, что вы предложите способ сделать это. Означает ли это, что мой метод eval должен возвращать пару C с манифестом, а не только C? - person Tala; 23.06.2010
comment
Я имею в виду, что ваш C должен хранить манифест. Попробуйте объявить его так: case class C[A <: AnyVal](val value:A)(implicit man: Manifest[A]) и использовать эти манифесты для преобразования их в нужные типы. - person Daniel C. Sobral; 23.06.2010
comment
Я изменил свой класс C, как вы советовали, но проблема все еще существует. Можете ли вы сказать мне, как мне нужно изменить код интерпретатора, показанный выше? - person Tala; 24.06.2010
comment
@Tala Вам нужно будет сделать что-то вроде case (l: C[Int], r: C[Int]) if l.man == manifest[Int] && r.man == manifest[Int] => l + r и так далее для каждой комбинации. - person Daniel C. Sobral; 24.06.2010
comment
:-) Это именно то, чего я пытался избежать. Я мог бы просто создать подклассы C, такие как «intC extends C [Int]», и на всякий случай перебрать все возможные комбинации, что намного дешевле, чем иметь дело с манифестами. Но поскольку существует множество типов и много операций, это приведет к огромному дублированию кода. Должен быть способ получше. - person Tala; 24.06.2010
comment
@Tala Вы должны избегать параметров типа, чтобы он работал таким образом, потому что они стираются во время выполнения. Если вам нужен тип во время выполнения, вам лучше пойти путем создания подклассов. Возможно, переделайте свое решение. - person Daniel C. Sobral; 24.06.2010
comment
Привет, Даниэль. Я все еще ищу решение (последнее будет связано с большим количеством дублирования кода) Могу ли я создать карту типов и имени функции для соответствующих функций преобразования, таких как '(Int, Double, SUM) - ›функция, которая их преобразует в один вид и складывает и т. д.? Затем мне нужно будет проверить типы левого и правого операндов и передать функцию, которая выполняет задание. это возможно и стоит ли делать? - person Tala; 24.06.2010