# Nesting Custom Types

Learn to define nested Haskell data types.

## We'll cover the following

## Defining nested types

When defining custom types with `data`

, we are not limited to using predefined types in the constructors. We can also nest custom types.

Let’s extend our `Geometry`

type (from the previous lesson) with location information. Remember, its definition was

```
data Geometry = Rectangle Double Double | Square Double | Circle Double deriving (Show)
```

The location of a shape should be the coordinates of its center point in the 2D plane. We thus identify a location by two doubles, its x and y coordinates.

```
data Coordinates = Coordinates Double Double deriving (Show)
```

Note that we are using `Coordinates`

here as both the name of the type as well as the name of the only constructor. This is fine, as types and constructors have different namespaces. By convention, types with a single constructor often have the same name as the constructor.

We can now create a new type for a shape with the coordinates of its center.

```
data LocatedShape = LocatedShape Geometry Coordinates deriving (Show)
```

Located shapes can be created by nesting constructors.

```
located = LocatedShape (Square 2) (Coordinates 2 3)
```

## Functions on nested types

Given a located shape, let’s write a function that takes another coordinate point and checks whether it is contained inside the shape.

```
containedIn :: Coordinates -> LocatedShape -> Bool
```

The function is used like this:

```
*Geometry> (Coordinates 5 3) `containedIn` (LocatedShape (Square 2) (Coordinates 3 3))
False
```

Here is our definition of `containedIn`

.

```
containedIn :: Coordinates -> LocatedShape -> Bool
(Coordinates x y) `containedIn` (LocatedShape shape (Coordinates cx cy)) =
case shape of
(Circle r) -> (cx - x)^2 + (cy - y)^2 <= r^2
(Rectangle a b) -> abs (cx - x) <= a / 2 && abs (cy - y) <= b / 2
(Square a) -> abs (cx - x) + abs (cy - y) <= a
```

At the beginning of the function equation, we are applying nested pattern matching on the located shape.

```
(LocatedShape shape (Coordinates cx cy))
```

We already deconstructed the nested `Coordinates`

value and bound the coordinates to `cx`

and `cy`

. On the other hand, the `shape`

variable will bind to the `Geometry`

value in the located shape, which we don’t yet fully match. We defer matching on the shape to define the function in one equation. This makes it more readable compared to the alternative of matching everything.

```
-- full pattern matching version
containedIn :: Coordinates -> LocatedShape -> Bool
(Coordinates x y) `containedIn` (LocatedShape (Circle r) (Coordinates cx cy)) = (cx - x)^2 + (cy - y)^2 <= r^2
(Coordinates x y) `containedIn` (LocatedShape (Rectangle a b) (Coordinates cx cy)) = abs (cx - x) <= a / 2 && abs (cy - y) <= b / 2
(Coordinates x y) `containedIn` (LocatedShape (Square a) (Coordinates cx cy)) = abs (cx - x) + abs (cy - y) <= a
```

The full pattern matching version contains a lot of duplicated code because the pattern matches in the three equations, which is why the delayed matching on the shape is preferable. When complex pattern matches are involved, it is cleaner to match the types that do not have several alternative constructors (like `Coordinates`

) once in the beginning. Then, use `case`

to continue matching on types that do have several alternative constructors (like `Geometry`

).

## Exercise: Pattern matching on custom types

As an exercise implement a function `move`

which takes a `LocatedShape`

and moves it to a new location. The direction of movement is given by a movement vector, which should be added to the coordinates of the shape.

```
data Vector = Vector Double Double
```

For example, if the shape is at `Coordinates 2 3`

and the movement vector, `Vector 5 1`

, is passed, the shape should move to `Coordinates 7 4`

. The `Geometry`

value of the shape should remain unchanged.

```
move (LocatedShape (Circle 5) (Coordinates 2 3)) (Vector 5 1) = LocatedShape (Circle 5) (Coordinates 7 4)
```

Get hands-on with 1200+ tech skills courses.