Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

More on generic Scala functions

Tags:

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))  
like image 399
eptx Avatar asked Sep 07 '11 16:09

eptx


People also ask

What is generic function in Scala?

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, [ ].

How do I use generic in Scala?

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*.

Which function is known as generic function?

A generic function is a function that is declared with type parameters. When called, actual types are used instead of the type parameters.

Does Scala support generics?

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.


2 Answers

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 
like image 149
missingfaktor Avatar answered Jan 05 '23 03:01

missingfaktor


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

like image 31
Dylan Avatar answered Jan 05 '23 03:01

Dylan