Abstract types in Scala

Amit Prasad
3 min readMay 16, 2020

--

Often as a developer one wonder how to write the code which can accommodate all the possible types on your numeric type operations or any other object. Java developers have that leverage to connect themselves to Generic programming and likewise other programming languages developer.
Scala makes it more granular for generic programming with the help of

  1. Abstract Type with Type parameters
  2. Abstract Type with Type aliases
  3. Code abstraction with both combination

Abstract Type with Type parameters :

Abstract type with parameters works traditionally like java and other JVM supported languages. Let’s see an example of the abstract type with Type parameters

trait AlgebricOperation[T] {
def add(a: T, b: T): T
def sub(a: T, b: T): T
def mul(a: T, b: T): T
def div(a: T, b: T): T
}

In above snippet we have AlgebricOperation with type T which can be passed of implemented method.

object AbstractType extends AlgebricOperation[Int] {
override def add(a: Int, b: Int): Int = a + b

override def sub(a: Int, b: Int): Int = a - b

override def mul(a: Int, b: Int): Int = a * b

override def div(a: Int, b: Int): Int = a / b
}

Here in AbstractType as we can see we are extending AlgebricOperation with type parameter Int so the operation will be performed on Int type a likewise for other types as well.

Abstract Type with Type aliases :

In this example, we will not pass the type as a parameter but instead, we will define the type in the implemented class as which we are interpreted in the same scope for type operation.

trait AlgebricOperationWithType {
type T
def add(a: T, b: T): T
def sub(a: T, b: T): T
def mul(a: T, b: T): T
def div(a: T, b: T): T
}

The above trait is defined to perform the operation on type T which can be seen in the trait scope.

Below is the code which can use this trait and pass the type as user wants for their operation.

object AbstractTypeWithTypeParam extends AlgebricOperationWithType {
type T = Int // here we are passing the type as Int to accomodate the types in AlgebricOperationWithType trait
override def add(a: Int, b: Int): Int = a + b

override def sub(a: Int, b: Int): Int = a - b

override def mul(a: Int, b: Int): Int = a * b

override def div(a: Int, b: Int): Int = a / b
}

Code abstraction with both combination :

In this example, we can use both parameterized types and type alias value to see how input and output can be accommodated using the combined technique.

trait StringOperation[T] {
type U
def operation: U
}

In the above trait T is defined as input type and U is defined as output type for the operation, now we will see how we can chain the operation based on the types

object StringOperationDemo extends App {
type inputTypeT = String

val lowerToUpper =
new StringOperation[inputTypeT] {
override type U = inputTypeT => String
override def operation: U = (string: inputTypeT) => string.toUpperCase
}
val stringL = List("India", "usa", "Germany", "Japan", "UK")
val upperL = stringL.map(lowerToUpper.operation)
upperL foreach println
}

In the above example, We can see inputTypeT as the parameter which is eventually of type String and an object lowerToUpper is created which is basically override the type U and tells explicitly to take input as inputTypeT(String) and transform the type into String and passed in operation to perform and send back the type as U(String).

These are the features makes scala more powerful and typesafe when we deal with different types.

--

--

Amit Prasad
Amit Prasad

Written by Amit Prasad

Engineer by profession, Scala | Data engineering | Distributed System Linkedin: https://www.linkedin.com/in/amitprasad119/

No responses yet