Semigroup

beginner

A semigroup for some given type `A` has a single operation (which we will call `combine`), which takes two values of type `A`, and returns a value of type `A`. This operation must be guaranteed to be associative. That is to say that:

``````(a.combine(b)).combine(c)
``````

must be the same as

``````a.combine(b.combine(c))
``````

for all possible values of a, b ,c.

There are instances of `Semigroup` defined for many types found in Arrow and the Kotlin std lib. For example, `Int` values are combined using addition by default but multiplication is also associative and forms another `Semigroup`.

Examples

Now that you’ve learned about the Semigroup instance for Int try to guess how it works in the following examples:

``````import arrow.*
import arrow.typeclasses.*
import arrow.instances.*

ForInt extensions { 1.combine(2) }
// 3
``````
``````import arrow.data.*
import arrow.instances.listk.semigroup.*

ListK.semigroup<Int>().run { listOf(1, 2, 3).k().combine(listOf(4, 5, 6).k()) }
// ListK(list=[1, 2, 3, 4, 5, 6])
``````
``````import arrow.core.*
import arrow.instances.option.monoid.*

Option.monoid<Int>(Int.semigroup()).run { Option(1).combine(Option(2)) }
// Some(3)
``````
``````Option.monoid<Int>(Int.semigroup()).run { Option(1).combine(None) }
// Some(1)
``````

Many of these types have methods defined directly on them, which allow for such combining, e.g. `+` on `List`, but the value of having a `Semigroup` typeclass available is that these compose.

Additionaly `Semigroup` adds `+` syntax to all types for which a Semigroup instance exists:

``````Option.monoid<Int>(Int.semigroup()).run {
Option(1) + Option(2)
}
// Some(3)
``````

Contents partially adapted from Scala Exercises Cat’s Semigroup Tutorial

Data types

 Module Data types arrow.core Either, Option, Try arrow.data ListK, MapK, NonEmptyList, SequenceK, SetK arrow.typeclasses Const