by Rewati Raman

01 Mar 2017

Algebraic data types(ADTs) are a functional programming concept. This should not be confused with Abstract data types. For example Tree is a abstract data type but not algebraic data type. Algebraic data type is data representation using defined algebraic functions or expressions. Definition of algebraic data type can simply also stated as data representation using Ands and Ors. For example: - a shape is a rectangle or a circle - a rectangle has a width and a height - a circle has a radius

“And” types such as rectangle and circle are called products and “Or” types such as shape are called coproducts. In Scala we typically represent products using case classes and coproducts using sealed traits.

```
scala> sealed trait Shape
defined trait Shape
scala> final case class Rectangle(width: Double, height: Double) extends Shape
defined class Rectangle
scala> final case class Circle(radius: Double) extends Shape
defined class Circle
scala> val rect: Shape = Rectangle(1, 2)
rect: Shape = Rectangle(1.0,2.0)
scala> val circ: Shape = Circle(1)
circ: Shape = Circle(1.0)
```

Shape are coproducts defined using trait. Rectangle and Circle are Product defined through case class. ADTs are completely type safe. The compiler has complete knowledge of the algebras we define, so it can help us write complete, correctly typed methods involving our types. Algebra in ADTs mean symbols we define, such as rectangle and circle and the rules for manipulating those symbols, encoded as methods.

```
scala> def area(shape: Shape): Double =
| shape match {
| case Rectangle(w, h) => w * h
| case Circle(r) => math.Pi * r * r
| }
area: (shape: Shape)Double
scala> area(rect)
res0: Double = 2.0
```

The above can also be achieved in another way. Scala standard library provides generic products in the form of Tuples and a generic coproduct in the form of Either.

```
scala> type Rectangle2 = (Double, Double)
defined type alias Rectangle2
scala> type Circle2 = Double
defined type alias Circle2
scala> type Shape2 = Either[Rectangle2, Circle2]
defined type alias Shape2
scala> val rect2: Shape2 = Left((3.0, 4.0))
rect2: Shape2 = Left((3.0,4.0))
scala> val circ2: Shape2 = Right(1.0)
circ2: Shape2 = Right(1.0)
scala> def area2(shape: Shape2): Double =
| shape match {
| case Left((w, h)) => w * h
| case Right(r) => math.Pi * r * r
| }
area2: (shape: Shape2)Double
scala> area2(rect2)
res2: Double = 12.0
```