更多关于通用Scala函数的信息

更多关于通用Scala函数的信息,scala,haskell,polymorphism,numeric,Scala,Haskell,Polymorphism,Numeric,尝试在Scala中实现以下Haskell函数(从Learn You a Haskell…),以便它可以与Int、Double等一起使用 doubleUs x y = x * 2 + y * 2 请注意,这与 这是我的尝试和错误。有人能解释一下发生了什么并提供解决方案吗。谢谢 scala> def doubleUs[A](x:A,y:A)(implicit numeric: Numeric[A]): A = numeric.plus(numeric.times(x,2),numeric.

尝试在Scala中实现以下Haskell函数(从Learn You a Haskell…),以便它可以与Int、Double等一起使用

doubleUs x y = x * 2 + y * 2 
请注意,这与

这是我的尝试和错误。有人能解释一下发生了什么并提供解决方案吗。谢谢

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)) 
scala>def doubleUs[A](x:A,y:A)(隐式数字:数字[A]):A=numeric.plus(numeric.times(x,2),numeric.times(y,2))
:34:错误:类型不匹配;
发现:Int(2)
所需:A
def doubleUs[A](x:A,y:A)(隐式数字:数字[A]):A=numeric.plus(numeric.times(x,2),numeric.times(y,2))

您使用的是
Int
literal
2
,但scala需要
Numeric
类型
A
。 具有一个实用程序函数-
def fromInt(x:Int):T
。这就是您想要使用的,因此将
2
的用法替换为
numeric.fromInt(2)


此外,由于数值实例定义了到Ops的隐式转换,您可以
导入数值。
,然后说
x*fromInt(2)+y*fromInt(2)
,您需要一些范围内的隐式转换:

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
}

除了@Dylan所说的,您还可以通过将
Numeric
implicit的内容导入到scope中,使其看起来不那么乏味,如下所示:

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

Dylan从本质上回答了这个问题,但无论如何,我建议使用上下文绑定语法而不是隐式参数(两者都是等价的,编译器会自动将前者重写为后者)


啊。。。通用数学在scala中看起来如此复杂…@fuzzxl是Java遗留和互操作性的结果。来自C#/F#/Haskell/Mathematica的背景,我不得不说,我的心非常高兴看到了这些丑陋的景象,这些丑陋的景象困扰着我在短暂接触Java/scala^^之后故意选择远离的语言!天堂里没有一个上帝不怜悯那些每天遭受如此混乱的人。@Cetin:在Scala,普通数学是丑陋的。但它可以做普通数学。C#,F#甚至不能以类型安全的方式进行普通数学运算。Mathematica是一种动态类型语言,这种比较没有意义。它被称为上下文绑定,而不是类型注释语法。
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
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)))
}