More on generic Scala functions

亡梦爱人 提交于 2019-12-04 15:41:30

问题


Trying to implement, in Scala, the following Haskell function (from Learn You a Haskell...) so that it works with Int, Double, etc.

doubleUs x y = x * 2 + y * 2 

Note that this is similar to Scala: How to define "generic" function parameters?

Here's my attempt and error. Can someone explain what's happening and offer a solution. Thanks.

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:


You are using the Int literal 2 but scala is expecting the Numeric type A. The Scala Numeric API has a utility function- def fromInt(x:Int): T. This is what you want to use, so replace your usage of 2 with 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)))

Also, since a Numeric instance defines an implicit conversion to an Ops, you can import numeric._ and then say x * fromInt(2) + y * fromInt(2).




回答2:


In addition to what @Dylan said, you can make it look a little less tedious by importing into scope the contents of Numeric implicit as shown below:

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:


You need some implicits in scope:

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 essentially answered, but for what it's worth, let me suggest to use the context bound syntax instead of the implicit argument (both are equivalent, and the former is automatically rewritten into the latter by the compiler).

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)))
}


来源:https://stackoverflow.com/questions/7337582/more-on-generic-scala-functions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!