尝试在Scala中实现以下Haskell函数(来自Learn You a Haskell ...),以便它可以与Int,Double等一起使用。
doubleUs x y = x * 2 + y * 2
请注意,这类似于Scala: How to define "generic" function parameters?
这是我的尝试和错误。有人可以解释正在发生的事情并提供解决方案。感谢。
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))
答案 0 :(得分:20)
除了@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
答案 1 :(得分:19)
您使用的是Int
文字2
,但scala期待Numeric
类型A
。
Scala Numeric 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)))
此外,由于Numeric实例定义了对Ops的隐式转换,您可以import numeric._
然后说x * fromInt(2) + y * fromInt(2)
。
答案 2 :(得分:11)
您需要在范围内隐含一些内容:
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
}
答案 3 :(得分:2)
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)))
}