Подробнее о общих функциях Scala
Попытка реализовать в Scala следующую функцию Haskell (от Learn You a Haskell...), чтобы она работала с Int, Double и т.д.
doubleUs x y = x * 2 + y * 2
Обратите внимание, что это похоже на Scala: Как определить "generic" параметры функции?
Здесь моя попытка и ошибка. Может кто-то объяснить, что происходит и предложить решение. Спасибо.
scala> def doubleUs[A](x:A,y:A)(implicit numeric: Numeric[A]): A = numeric.plus(numeric.times(x,2),numeric.times(y,2))
<console>:34: error: type mismatch;
found : Int(2)
required: A
def doubleUs[A](x:A,y:A)(implicit numeric: Numeric[A]): A = numeric.plus(numeric.times(x,2),numeric.times(y,2))
Ответы
Ответ 1
Вы используете Int
literal 2
, но scala ожидает тип Numeric
A
.
Scala Числовой API имеет функцию утилиты def fromInt(x:Int): T
. Это то, что вы хотите использовать, поэтому замените использование 2
на numeric.fromInt(2)
def doubleUs[A](x:A,y:A)(implicit numeric: Numeric[A]): A =
numeric.plus (numeric.times (x, numeric.fromInt (2)), numeric.times (y, numeric.fromInt (2)))
Кроме того, поскольку числовой экземпляр определяет неявное преобразование в Ops, вы можете import numeric._
и затем сказать x * fromInt(2) + y * fromInt(2)
.
Ответ 2
В дополнение к тому, что сказал @Dylan, вы можете заставить его выглядеть немного менее утомительным, импортируя в область содержимого Numeric
неявное, как показано ниже:
scala> def doubleUs[N](x: N, y: N)(implicit ev: Numeric[N]) = {
| import ev._
| x * fromInt(2) + y * fromInt(2)
| }
doubleUs: [N](x: N, y: N)(implicit ev: Numeric[N])N
scala> doubleUs(3, 4)
res9: Int = 14
scala> doubleUs(8.9, 1.2)
res10: Double = 20.2
Ответ 3
Вам понадобятся некоторые неявки в области:
def doubleUs[A](x: A, y: A)(implicit num: Numeric[A]) = {
import num._
implicit def fromInt(i: Int) = num.fromInt(i)
x * 2 + y * 2
}
Ответ 4
Dylan, по сути, ответил, но для чего это стоит, позвольте мне предложить использовать связанный с контекстом синтаксис вместо неявного аргумента (оба эквивалентны, и первый автоматически переписывается последним компилятором).
def doubleUs[A : Numeric](x : A, y : A) : A = {
val num = implicitly[Numeric[A]]
import num.{plus,times,fromInt}
plus(times(x, fromInt(2)), times(y, fromInt(2)))
}