How to write a Scala method that takes a simple generic type

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is a short recipe, Recipe 19.2, “How to write a Scala method that takes a simple generic type.”

Problem

You’re not concerned about type variance, and want to create a Scala method (or function) that takes a generic type, such as a method that accepts a Seq[A] parameter.

Solution

As with Scala classes, specify the generic type parameters in brackets, like [A]. For example, when creating a lottery-style application to draw a random name from a list of names, you might follow the “Do the simplest thing that could possibly work” credo, and initially create a method without using generics:

def randomName(names: Seq[String]): String = {
    val randomNum = util.Random.nextInt(names.length)
    names(randomNum)
}

As written, this works with a sequence of String values:

val names = Seq("Aleka", "Christina", "Tyler", "Molly")
val winner = randomName(names)

Then, at some point in the future you realize that you could really use a general-purpose method that returns a random element from a sequence of any type. So, you modify the method to use a generic type parameter, like this:

def randomElement[A](seq: Seq[A]): A = {
    val randomNum = util.Random.nextInt(seq.length)
    seq(randomNum)
}

With this change, the method can now be called on a variety of types:

randomElement(Seq("Aleka", "Christina", "Tyler", "Molly"))
randomElement(List(1,2,3))
randomElement(List(1.0,2.0,3.0))
randomElement(Vector.range('a', 'z'))

Note that specifying the method’s return type isn’t necessary, so you can simplify the signature slightly, if desired:

// change the return type from ':A =' to just '='
def randomElement[A](seq: Seq[A]) = { ...

... this post is sponsored by my books ...
 

Discussion

This is a simple example that shows how to pass a generic collection to a method that doesn’t attempt to mutate the collection. See Recipes 19.4 and 19.5 for more complicated situations you can run into.