**What Is Algebraic Data Type in Haskell?**

Haskell is a functional programming language that embraces strong static typing. One of the key features that sets Haskell apart from other programming languages is its support for __algebraic data types__. Algebraic data types (ADTs) allow programmers to define custom data structures by combining existing types in a flexible and powerful way.

## Defining Algebraic Data Types

In Haskell, we can define ADTs using the __data__ keyword. The syntax for defining an ADT consists of two parts: the type constructor and the data constructors. The type constructor defines the name of the ADT, while the data constructors define the possible values that can inhabit that type.

Let’s take a look at an example to understand this better. Suppose we want to define a simple ADT called **Shape**, which can represent either a circle or a rectangle. We can do this as follows:

```
data Shape = Circle Float | Rectangle Float Float
```

In this example, **Shape** is the type constructor, and it has two data constructors: **Circle** and **Rectangle**. The **Circle** constructor takes a single argument, which represents the radius of the circle. The **Rectangle** constructor takes two arguments: width and height.

## Patterning Matching with Algebraic Data Types

One of the main benefits of using ADTs in Haskell is their ability to easily pattern match on different cases. Pattern matching allows us to destructure values of an ADT and handle each case separately.

Continuing with our previous example, suppose we have a function called **area** that calculates the area of a shape. We can pattern match on the data constructors of the **Shape** type to implement this function:

```
area :: Shape -> Float
area (Circle r) = pi * r * r
area (Rectangle w h) = w * h
```

In this code snippet, we define two cases for the **area** function using pattern matching. If the shape is a circle, we calculate its area using the formula πr², where r is the radius. If the shape is a rectangle, we calculate its area using the formula width × height.

## Nested Algebraic Data Types

ADTs in Haskell can also be nested within each other. This allows us to define more complex data structures by combining multiple ADTs.

Let’s consider an example where we want to define an ADT called **Tree**, which represents a binary tree. Each node in this tree can be either empty or contain a value and two child nodes.

```
data Tree a = Empty | Node a (Tree a) (Tree a)
```

In this example, **Tree** is the type constructor that takes a type parameter *a*. The data constructors are **Empty**, representing an empty tree, and **Node**, representing a node with a value and two child trees.

### In Conclusion

Algebraic data types are one of Haskell’s most powerful features. They allow us to create custom data structures by combining existing types in flexible ways. With pattern matching and nested ADTs, we can handle different cases and build complex data structures effortlessly.