# Identity

`Identity[A]`

describes a data type with an associative combining operation that also has an identity element.

Its signature is:

```
trait Associative[A] {
def combine(left: => A, right: => A): A
}
trait Identity[A] extends Associative[A] {
def identity: A
}
```

The identity element is a neutral value that does not have any structure itself and so combining it with any other value just leaves the structure of the other value unchanged. For instance, an empty `Chunk`

is an identity element with respect to the `++`

operator.

It is important to note here that while `Identity`

describes a data type with an identity element, that identity element only has meaning in relation to the binary operator. Specifically, combining any value of type `A`

with the identity element with the `combine`

operator must return the value unchanged.

```
a <> identity === a
identity <> a === a
```

For example, zero is an identity element with respect to addition, but not with respect to multiplication. Similarly, `true`

is an identity element with respect to logical conjunction, but `false`

is an identity element with respect to logical disjunction.

Many associative combinining operations also have an identity element, but some do not.

For example the minimum or maximum of two values on which a total ordering is defined does not have an identity element. Neither does the first or last of two values or the concatenation of collections that cannot be empty.

If we import `zio.prelude._`

we can use the same `<>`

operator as we did to combine two values for which an `Associative`

instance was defined.

Since the `identity`

value is a single value and not an operator we access it slightly different. Typically we will use the `apply`

method on the `Identity`

companion object.

```
import zio.prelude._
import zio.prelude.newtypes._
val zero: Int =
Identity[Sum[Int]].identity
// zero: Int = 0
```

The `apply`

operator on the `Identity`

companion object "looks up" the instance of the type class for the specified type, failing with a compilation error if the instance cannot be found. This operator is available on every functional abstraction in ZIO Prelude and is sometimes referred to as its "summoner".

Notice also here that we are using the `Sum`

new type to specify that we are interested in the identity element with respect to addition rather than another operator such as multiplication. See the section on new types in the documentation for the `Associative`

abstraction for a discussion of the use of new types to disambiguate type class instances.

The main value the identity element adds over just having the associative combining operation is the ability to handle cases where we do not have any value of the type at all.

With the `Associative`

abstraction we know how to combine any two values of type `A`

. So if we have one or more values of type `A`

we can always combine them all together by repeatedly applying the `combine`

operator.

However, we need at least one `A`

value to get the process started. If we don't have any `A`

value initially we have no way to create one with the `Associative`

abstraction alone.

To see this, consider the example of computing the minimum value in a collection.

If the collection has exactly one element we can just return it. And if it has more than one element we can combine them using the `min`

operator until we only have a single value.

But what do we do if the collection has no values? We can't do anything so we return an `Option`

that is a `Some`

with the minimum if there is at least one element and `None`

otherwise.

```
import zio.prelude._
import zio.prelude.newtypes._
def min[A: Ord](as: List[A]): Option[A] =
Max.wrapAll(as) match {
case h :: t => Some(t.foldLeft(h)(_ <> _))
case Nil => None
}
```

Compare this to computing the sum of a collection. Now If the collection is empty we can just return the identity value.

```
def sum[A](as: List[A])(implicit identity: Identity[Sum[A]]): A =
Sum.wrapAll(as).foldLeft(identity.identity)(identity.combine(_, _))
```

The identity element handles the case where the collection is empty for us, allowing us to always return a summary value.

If we don't have an identity value we can only guarantee that we can return a summary value if the collection is known not to be empty, such as a `NonEmptyChunk`

or a `NonEmptyList`

. This is why these data types can be valuable.

If the collection could be empty and we only have a `combine`

operator we may not be able to return a summary value and the best we can do is an `Option`

.

One way to think of this is that the `None`

case of the `Option`

handles the possibility of failure. Another is that the `None`

case of the `Option`

provides the identity element for the `combine`

operator, which we can express like this:

```
implicit def OptionIdentity[A: Associative]: Identity[Option[A]] =
new Identity[Option[A]] {
def combine(left: => Option[A], right: => Option[A]): Option[A] =
(left, right) match {
case (Some(a1), Some(a2)) => Some(a1 <> a2)
case (_, None) => left
case (None, _) => right
case (_, _) => None
}
def identity: Option[A] = None
}
```

This says that we can define an `Identity`

instance for any `Option[A]`

as long as there is an `Associative`

instance defined for `A`

. The `Option`

provides the "free" structure of an identity element to go from just having an associative `combine`

operator to having an `identity`

element.

This can be useful to keep in mind if you are dealing with a collection that could be empty and need an `Identity`

instance but only have an `Associative`

instance. You can always map your collection type to an `Option`

and then you will have an `Identity`

instance.

Data types with an associative `combine`

operator and an `identity`

element are very common. With an `Identity`

instance defined for them and the other tools in ZIO Prelude you are in a good position to handle working with even complex data types.