Структурированная типизация в Scala не работает с Double?

Я пытаюсь сделать следующий код:

def sum(e: { def *(x: Double): Double}) = e * 2.0

Проблема в том, что это не работает с числовыми классами:

sum(20.0)
<console>:9: error: type mismatch;
 found   : Double(10.0)
 required: AnyRef{def *(x: Double): Double}
              algo(10.0)

sum(10)
<console>:9: error: type mismatch;
 found   : Int(10)
 required: AnyRef{def *(x: Double): Double}
              algo(10)

Что-то не так с моим кодом?

Ответ 1

Scala структурный тип не требует AnyRef.

Конечно, следующее объявление метода не работает должным образом.

def sum(e: { def *(x: Double): Double }) = e * 2.0

Причиной этого является приведенный выше код, который интерпретируется следующим образом:

def sum(e: AnyRef { def *(x: Double): Double}) = e * 2.0

Если вы явно укажете Any, код работает:

scala> def sum(e: Any { def *(x: Double): Double }) = e * 2.0
sum: (e: Any{def *(x: Double): Double})Double

scala> sum(10.0)
res0: Double = 20.0

Ответ 2

Ваш метод sum ожидает подтип AnyRef, а Double и другие числовые типы являются подтипами AnyVal. Вместо этого вам следует использовать Numeric typeclass.

def sum[E:Numeric](e:E) = {
  val n = implicitly[Numeric[E]]
  n.toDouble(e) * 2
}