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))
In Scala, forming a Generic Class is extremely analogous to the forming of generic classes in Java. The classes that takes a type just like a parameter are known to be Generic Classes in Scala. This classes takes a type like a parameter inside the square brackets i.e, [ ].
To use a generic class, put the type in the square brackets in place of A . Class Apple and Banana both extend Fruit so we can push instances apple and banana onto the stack of Fruit . Note: subtyping of generic types is *invariant*.
A generic function is a function that is declared with type parameters. When called, actual types are used instead of the type parameters.
Most Scala generic classes are collections, such as the immutable List, Queue, Set, Map, or their mutable equivalents, and Stack. Collections are containers of zero or more objects. We also have generic containers that aren't so obvious at first.
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
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)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With