# Combining values of the same type

beginner

## Having one or more values

#### Problem

I have:

• One or more values of type `A`.

I want to have:

• A single value of type `A`.

#### Solution

If you have several values of the same type (at least one), you can `combine` them into a single value. `combine` is a binary operation; i.e., you need two values of type `A` to combine them into one.

If you have more than two elements, you can either chain multiple `combine` calls, or use `combineAll`, which accepts a variadic number of parameters.

This operation is available in the Semigroup type class, and it is an associative operation. Your type must conform to `Semigroup` in order to have `combine` available.

#### Example

Basic types like numeric types or Strings already conform to `Semigroup` in Bow. For instance, we can combine `Int` values like:

``````let x = 2
let y = 5
let z = 8

x.combine(y) // Returns 7
Int.combineAll(x, y, z) // Returns 15
``````

The operation is associative; that is, we can first combine `x` and `y`, and then `z`, or first `y` and `z`, and then `x`.

``````x.combine(y).combine(z) == x.combine(y.combine(z))
``````
``````let a = "Hello"
let b = "World"

a.combine(b) != b.combine(a)
``````

## Having zero or more values

#### Problem

I have:

• Zero or more values of type `A`.

I want to have:

• A single value of type `A`.

#### Solution

The problem described here is similar to the problem above, with the difference of potentially having no values. We can use `combine`, but we need to provide a default value when no values are combined.

This default value is `empty` and it is available in the Monoid type class. `empty` has the property of being combinable with any other element of the type, yielding the same value it is combined with.

#### Example

Like with Semigroups, basic types in Swift already conform to `Monoid` in Bow.

``````x.combine(Int.empty()) // Returns x
Int.empty().combine(x) // Returns x
``````

#### Problem

I have my own type and I need to combine elements of this type.

#### Solution

You need to use Swift `extension` mechanisms to make your type conform to `Semigroup` and `Monoid`, guaranteeing that your implementation honors the properties of both type classes.

#### Example

Consider a type to model a shopping cart:

``````struct ShoppingCart<Product> {
let products: [Product]
let amount: Double
}
``````

If I need to give it the ability to combine its values, I need to determine how each of its properties are combined with the ones in other values. In this case:

• `products` can be combined by concatenating the arrays of the two carts that are being combined.
• `amount` can be combined by adding the amounts of the two carts.

Therefore, I can make an `extension` to conform to `Semigroup`:

``````extension ShoppingCart: Semigroup {
func combine(_ other: ShoppingCart<Product>) -> ShoppingCart<Product> {
ShoppingCart(
products: self.products + other.products,
amount: self.amount + other.amount
)
}
}
``````

If I need to give it the ability to have an empty value, I need to determine how each of its properties need to be initialized to an empty value. In this case:

• `products` can be initialized to an empty array.
• `amount` can be initialized to `0.0`.

Therefore, I can make an `extension to conform to `Monoid`:

``````extension ShoppingCart: Monoid {
static func empty() -> ShoppingCart<Product> {
ShoppingCart(
products: [],
amount: 0.0
)
}
}
``````

## Are all types that conform to Semigroup also conform to Monoid?

If your type conforms to `Monoid` it also must conform to `Semigroup`, but the reverse is not true. You may be able to combine values of a type, but not be able to provide an empty value.

One example of this is the `NonEmptyArray` type, which, as its name suggests, is never empty; therefore, it cannot provide an empty value for the combination.