# Semi-Group

A semi-group is a typeclass which can apply associative binary operation. So if a type is a semi-group, its binary operation `append` can be applied. It's associative so `SemiGroup[A].append(SemiGroup[A].append(a, b), c)` is equal to `SemiGroup[A].append(a, SemiGroup[A].append(b, c))`

e.g.)

``import just.fp._def foo[A](x: Int, y: Int, f: Int => A)(implicit S: SemiGroup[A]): A =  S.append(f(x), f(y))// or with context bounddef foo[A: SemiGroup](x: Int, y: Int, f: Int => A): A =  SemiGroup[A].append(f(x), f(y))``

If there is a typeclass instance of `SemiGroup` for a type `A`, `mappend` method or a convenient `|+|` infix operator can be used like this.

e.g.) There is already a SemiGroup typeclass instance for `Int` in `just-fp` so you can do

``import just.fp.syntax._``
``1.mappend(2)// res0: Int = 31 |+| 2// res1: Int = 3``

Typeclass instances for the following typeclasses are available in `just-fp`.

• `SemiGroup[List[A]]`
``List(1, 2, 3) |+| List(4, 5, 6)// res2: List[Int] = List(1, 2, 3, 4, 5, 6)List(1, 2, 3).mappend(List(4, 5, 6))// res3: List[Int] = List(1, 2, 3, 4, 5, 6)``
• `SemiGroup[Vector[A]]`
``Vector(1, 2, 3) |+| Vector(4, 5, 6)// res4: Vector[Int] = Vector(1, 2, 3, 4, 5, 6)Vector(1, 2, 3).mappend(Vector(4, 5, 6))// res5: Vector[Int] = Vector(1, 2, 3, 4, 5, 6)``
• `SemiGroup[String]`
``"abc" |+| "def"// res6: String = "abcdef""abc".mappend("def")// res7: String = "abcdef"``
• `SemiGroup[Byte]`
``1.toByte |+| 2.toByte// res8: Byte = 31.toByte.mappend(2.toByte)// res9: Byte = 3``
• `SemiGroup[Short]`
``1.toShort |+| 2.toShort// res10: Short = 31.toShort.mappend(2.toShort)// res11: Short = 3``
• `SemiGroup[Char]`
``'A' |+| '1'// res12: Char = 'r''A'.mappend('1')// res13: Char = 'r'``
• `SemiGroup[Int]`
``1 |+| 2// res14: Int = 31.mappend(2)// res15: Int = 3``
• `SemiGroup[Long]`
``1L |+| 2L// res16: Long = 3L1L.mappend(2L)// res17: Long = 3L``
• `SemiGroup[BigInt]`
``BigInt(1) |+| BigInt(2)// res18: BigInt = 3BigInt(1).mappend(BigInt(2))// res19: BigInt = 3``
• `SemiGroup[BigDecimal]`
``BigDecimal(1) |+| BigDecimal(2)// res20: BigDecimal = 3BigDecimal(1).mappend(BigDecimal(2))// res21: BigDecimal = 3``
• `SemiGroup[Option[A]]` if there is a typeclass instance of `SemiGroup[A]`.
``1.some |+| 2.some// res22: Option[Int] = Some(value = 3)1.some.mappend(2.some)// res23: Option[Int] = Some(value = 3)``

NOTE: There might be an associativity issue with `BigDecimal` if it's created with other `MathContext` than `MathContext.UNLIMITED` and the number is big enough in Scala 2.13.