I am trying to understand the type parameters when applied to a function.
I would like to use Generic Types in the below method but using String and Int for my understa
Question: What's the difference between these 3 methods?
def myfunc1[X](f:String => X):X =
Integer.min(1,2)
def myfunc2[Int](f:String => Int):Int =
Integer.min(1,2)
def myfunc3[IDontGetTypeParameters](f:String => IDontGetTypeParameters):IDontGetTypeParameters =
Integer.min(1,2)
Answer: Nothing. From the compiler's point of view they are the same, and they fail to compile for the same reason: each is defined to return the type of the type parameter but tries to return an integer (Scala.Int
) instead.
Try
def myfunc(f:String => Int):Int = {
Integer.min(1,2)
}
When you write def myfunc[Int](f:String => Int):Int
you declare type parameter Int
, which hides standard type scala.Int
. This is the same as if you declared def myfunc[A](f:String => A):A
. When you remove return type it's inferred to be scala.Int
, i.e. def myfunc[A](f:String => A)
is def myfunc[A](f:String => A):Int
It's good trying to make your own examples, but have you tried any examples from books, articles or tutorials? There's probably a good one in Scala for the Impatient by Cay Horstmann.
Here's a decent example from the Tour de Scala:
def listOfDuplicates[A](x: A, length: Int): List[A] = {
if (length < 1)
Nil
else
x :: listOfDuplicates(x, length - 1)
}
Sometimes you can omit the type parameter, but let's ignore that for now and declare the types explicitly:
listOfDuplicates[Int](43, 5) // Should give a list with 43 five times
listOfDuplicates[String]("Hello, world! ", 3) // "Hello, world!" thrice
listOfDuplicates[(Int, Int)]((0, 1), 8) // The pair (0, 1) eight times
This shows that A
can be Int
, String
, (Int, Int)
or just about anything else we can think of. Not sure you'd ever have a practical need for this, but you can even do something like this:
def wrapLength(str: String): Int = str.length
listOfDuplicates[String => Int](wrapLength(_), 2)
Here's a Scastie snippet in which you can play around with this.
If you want to use generics, first you have to understand that the name of the variable types starts capitalized and they are names, just that so [Int]
in your function is the name of the type variable, an example:
object Main extends App{
val f: String => Int = s => 4
println(myfunc(f, "nothing useful"))
def myfunc[A,B](f:A => B, x: A):B = {
f(x)
}
}
here the names are A
and B
and the return type is of type B
Your generic type name shouldn't be one of the reserved words in Scala. Int itself is a reserved word for a type. In this cases, for simplicity and understanding, we use some basic characters like T or R as the generic type if you really keen to use generics for other functions.
A quick one liner:
def myfunc(f:String => Int):Int = Integer.min(1,2)