Почему на неявный поиск влияет параметр несвязанного типа? - PullRequest
5 голосов
/ 05 февраля 2012

Рассмотрим этот упрощенный фрагмент функциональности некоторых единиц измерения в Scala:

object UnitsEx {
  case class Quantity[M <: MInt, T: Numeric](value: T) {
    private val num = implicitly[Numeric[T]]
    def *[M2 <: MInt](m: Quantity[M2, T]) = 
      Quantity[M, T](num.times(value, m.value))
  }

  implicit def measure[T: Numeric](v: T): Quantity[_0, T] = Quantity[_0, T](v)
  implicit def numericToQuantity[T: Numeric](v: T): QuantityConstructor[T] = 
    new QuantityConstructor[T](v)

  class QuantityConstructor[T: Numeric](v: T) {
    def m = Quantity[_1, T](v)
  }

  sealed trait MInt
  final class _0 extends MInt
  final class _1 extends MInt
}

Этот фрагмент показывает использование и ошибку компилятора, которую я получаю в настоящее время:

import UnitsEx._

(1 m) * 1 // Works
1 * (1 m) // Doesn't work:
/*
<console>:1: error: overloaded method value * with alternatives:
(x: Double)Double <and>
(x: Float)Float <and>
(x: Long)Long <and>
(x: Int)Int <and>
(x: Char)Int <and>
(x: Short)Int <and>
(x: Byte)Int
cannot be applied to (UnitsEx.Quantity[UnitsEx._1,Int])
1 * (1 m)
^
*/

Обертывание 1 с measure решит проблему, но почему не применяется неявный в области видимости?

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

object UnitsEx2 {   
  case class Quantity[T: Numeric](value: T) {
    private val num = implicitly[Numeric[T]]
    def *(m: Quantity[T]) = Quantity[T](num.times(value, m.value))
  }

  implicit def measure[T: Numeric](v: T): Quantity[T] = Quantity[T](v)
  implicit def numericToQuantity[T: Numeric](v: T): QuantityConstructor[T] = 
    new QuantityConstructor[T](v)

  class QuantityConstructor[T: Numeric](v: T) {
    def m = Quantity[T](v)
  }
}

Это ожидаемое или известное ограничение проверки типов?

1 Ответ

1 голос
/ 06 февраля 2012

Если вы переименуете оператор *, например, mult, то 1 mult (1 m) работает в обоих случаях.Это не отвечает на ваш вопрос, но намекает на то, что, возможно, имеется некоторое вмешательство в сильно перегруженный оператор *.

...