Группа

Формальное определение

Группа G — это моноид с обратным \(g^{-1}\) для каждого элемента g.

Множество \(G\) с заданной на нём бинарной операцией +: \(G \times G \to G\) называется группой \((G, +)\), если выполнены следующие аксиомы:

Первые три закона наследуются от моноида.

Определение в виде кода на Scala

trait Group[A] extends Monoid[A]:
  extension (a: A) 
    def inverse: A

Законы в виде кода на Scala

trait GroupLaw extends MonoidLaw:
  def checkGroupLaw[A: Group](x: A, y: A, z: A): ValidatedNel[String, Unit] =
    checkMonoidLaw(x, y, z) combine
      check(
        Group[A].combine(x, Group[A].inverse(x)) == Group[A].empty,
        "inverse law 1: x + (-x) = 0"
      ) combine
      check(
        Group[A].combine(Group[A].inverse(x), x) == Group[A].empty,
        "inverse law 2: (-x) + x = 0"
      )

Примеры

Числа относительно сложения с 0

given Group[Int] with
  val empty                           = 0
  def combine(x: Int, y: Int): Int    = x + y
  extension (a: Int) def inverse: Int = -a

В примере ниже числитель и знаменатель надо сокращать на НОД и "нормализовывать" знак с проверкой на n ≠ 0, d ≠ 0, но в упрощенном варианте группа для рациональных чисел будет выглядеть так:

final case class Rational(n: Int, d: Int):
  def *(that: Rational): Rational =
    Rational(n * that.n, d * that.d)

given Group[Rational] with
  val empty: Rational                             = Rational(1, 1)
  def combine(x: Rational, y: Rational): Rational = x * y
  extension (a: Rational) def inverse: Rational   = Rational(a.d, a.n)

Реализация

Реализация в Cats

import cats.*, cats.syntax.all.*

1.inverse() // -1

assert((1 |+| 1.inverse()) === Monoid[Int].empty)

Реализация в Spire

import spire.algebra.Group
import spire.syntax.group.*

1.inverse       // -1
1 |+| 1.inverse // 0

Ссылки: