Semigroups are a simple functional concept which essentially allows us to take many objects and return a single object. It’s similar to reduce in that respect.

The most basic implementation of a semigroup is: (A, A) -> A . You might look at this and think, this would be perfect for an infix operator like + . You would be correct, in Haskell the operator is <> so as not to clash with existing + functionality, since the implementation may differ.

In Swift, we can implement a Semigroup like so:

infix operator <>: AdditionPrecedence public protocol Semigroup {

func combine(with other: Self) -> Self

static func <> (lhs: Self, rhs: Self) -> Self

} extension Semigroup {

public static func <> (lhs: Self, rhs: Self) -> Self {

return lhs.combine(with: rhs)

}

}

Many Swift types already are already using Semigroup logic including Numbers, Strings, and Arrays. They are all associative with the + operator. Therefore, we can extend these types to also also use the <> operator.

extension Numeric where Self: Semigroup {

public func combine(with other: Self) -> Self {

return self + other

}

} extension Int: Semigroup { } extension Array: Semigroup {

public func combine(with other: Array) -> Array {

return self + other

}

} extension String: Semigroup {

public func combine(with other: String) -> String {

return self + other

}

} extension Bool: Semigroup {

public func combine(with other: Bool) -> Bool {

return self && other

}

}

Now we can write a simple function to concatenate any type of Semigroup:

public func concat<S: Semigroup>(_ values: [S], initial: S) -> S {

return values.reduce(initial, <>)

}

This function just reduces the amount of <> symbols in our code, which will also help the compiler.

Now we can combine a bunch of values like so:

let a = true

let b = true

let c = false concat([a, b, c], initial: true) // false

We can also combine arrays using this functionality:

let spicy = ["Pepper", "Chilli"]

let sweet = ["Mango", "Pineapple"]

let sour = ["Lemon", "Sauerkraut"] let dish = concat([spicy, sweet, sour], initial: []) // ["Pepper", "Chilli", "Mango", "Pineapple", "Lemon", "Sauerkraut"]

Now that we have this operator we can use it for our own types too. All we have to define is a way of combining them.