beginner

**I have**:

- One or more values of type
`A`

.

**I want to have**:

- A single value of type
`A`

.

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.

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)
```

**I have**:

- Zero or more values of type
`A`

.

**I want to have**:

- A single value of type
`A`

.

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.

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
```

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

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.

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
)
}
}
```

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.