flix

0.78.0

Group.flix

/*
 *  Copyright 2022 Jakob Schneider Villumsen
 *
 * Use of this source code is governed by the Apache 2.0 license
 * that can be found in the LICENSE.md file.
 */

///
/// Trait for types that form a group, and its functions.
///
pub mod Group {

    ///
    /// Trait for types that form a group.
    ///
    /// The default instances for numbers define the additive inverse in the real numbers.
    ///
    pub trait Group[a] with Monoid[a] {

        ///
        /// Returns the neutral element.
        ///
        pub def empty(): a =
            Monoid.empty()

        ///
        /// Returns the inverse element of `x`.
        ///
        pub def inverse(x: a): a

        ///
        /// Returns the result of combining `x` and `y` using `Monoid`'s combine.
        ///
        pub def combine(x: a, y: a): a =
            Monoid.combine(x, y)

        ///
        /// Returns `y` removed from `x`.
        ///
        /// Equivalent to `Group.combine(x, Group.inverse(y))`
        ///
        pub def remove(x: a, y: a): a =
            Group.combine(x, Group.inverse(y))
    }

    instance Group[Unit] {
        pub def inverse(_: Unit): Unit = ()
    }

    instance Group[Int8] {
        pub def inverse(x: Int8): Int8 = -x
        redef remove(x: Int8, y: Int8): Int8 = x - y
    }

    instance Group[Int16] {
        pub def inverse(x: Int16): Int16 = -x
        redef remove(x: Int16, y: Int16): Int16 = x - y
    }

    instance Group[Int32] {
        pub def inverse(x: Int32): Int32 = -x
        redef remove(x: Int32, y: Int32): Int32 = x - y
    }

    instance Group[Int64] {
        pub def inverse(x: Int64): Int64 = -x
        redef remove(x: Int64, y: Int64): Int64 = x - y
    }

    instance Group[BigInt] {
        pub def inverse(x: BigInt): BigInt = -x
        redef remove(x: BigInt, y: BigInt): BigInt = x - y
    }

    instance Group[Float32] {
        pub def inverse(x: Float32): Float32 = -x
        redef remove(x: Float32, y: Float32): Float32 = x - y
    }

    instance Group[Float64] {
        pub def inverse(x: Float64): Float64 = -x
        redef remove(x: Float64, y: Float64): Float64 = x - y
    }

    instance Group[BigDecimal] {
        pub def inverse(x: BigDecimal): BigDecimal = -x
        redef remove(x: BigDecimal, y: BigDecimal): BigDecimal = x - y
    }

    instance Group[(a1, a2)] with Group[a1], Group[a2] {
        pub def inverse(x: (a1, a2)): (a1, a2) = match x {
            case (a1, a2) => (Group.inverse(a1), Group.inverse(a2))
        }
    }

    instance Group[(a1, a2, a3)] with Group[a1], Group[a2], Group[a3] {
        pub def inverse(x: (a1, a2, a3)): (a1, a2, a3) = match x {
            case (a1, a2, a3) => (Group.inverse(a1), Group.inverse(a2), Group.inverse(a3))
        }
    }

    instance Group[(a1, a2, a3, a4)] with Group[a1], Group[a2], Group[a3], Group[a4] {
        pub def inverse(x: (a1, a2, a3, a4)): (a1, a2, a3, a4) = match x {
            case (a1, a2, a3, a4) => (Group.inverse(a1), Group.inverse(a2), Group.inverse(a3), Group.inverse(a4))
        }
    }

    instance Group[(a1, a2, a3, a4, a5)] with Group[a1], Group[a2], Group[a3], Group[a4], Group[a5] {
        pub def inverse(x: (a1, a2, a3, a4, a5)): (a1, a2, a3, a4, a5) = match x {
            case (a1, a2, a3, a4, a5) => (Group.inverse(a1), Group.inverse(a2), Group.inverse(a3), Group.inverse(a4), Group.inverse(a5))
        }
    }

    instance Group[(a1, a2, a3, a4, a5, a6)] with Group[a1], Group[a2], Group[a3], Group[a4], Group[a5], Group[a6] {
        pub def inverse(x: (a1, a2, a3, a4, a5, a6)): (a1, a2, a3, a4, a5, a6) = match x {
            case (a1, a2, a3, a4, a5, a6) => (Group.inverse(a1), Group.inverse(a2), Group.inverse(a3), Group.inverse(a4), Group.inverse(a5), Group.inverse(a6))
        }
    }

    instance Group[(a1, a2, a3, a4, a5, a6, a7)] with Group[a1], Group[a2], Group[a3], Group[a4], Group[a5], Group[a6], Group[a7] {
        pub def inverse(x: (a1, a2, a3, a4, a5, a6, a7)): (a1, a2, a3, a4, a5, a6, a7) = match x {
            case (a1, a2, a3, a4, a5, a6, a7) => (Group.inverse(a1), Group.inverse(a2), Group.inverse(a3), Group.inverse(a4), Group.inverse(a5), Group.inverse(a6), Group.inverse(a7))
        }
    }

    instance Group[(a1, a2, a3, a4, a5, a6, a7, a8)] with Group[a1], Group[a2], Group[a3], Group[a4], Group[a5], Group[a6], Group[a7], Group[a8] {
        pub def inverse(x: (a1, a2, a3, a4, a5, a6, a7, a8)): (a1, a2, a3, a4, a5, a6, a7, a8) = match x {
            case (a1, a2, a3, a4, a5, a6, a7, a8) => (Group.inverse(a1), Group.inverse(a2), Group.inverse(a3), Group.inverse(a4), Group.inverse(a5), Group.inverse(a6), Group.inverse(a7), Group.inverse(a8))
        }
    }

    instance Group[(a1, a2, a3, a4, a5, a6, a7, a8, a9)] with Group[a1], Group[a2], Group[a3], Group[a4], Group[a5], Group[a6], Group[a7], Group[a8], Group[a9] {
        pub def inverse(x: (a1, a2, a3, a4, a5, a6, a7, a8, a9)): (a1, a2, a3, a4, a5, a6, a7, a8, a9) = match x {
            case (a1, a2, a3, a4, a5, a6, a7, a8, a9) => (Group.inverse(a1), Group.inverse(a2), Group.inverse(a3), Group.inverse(a4), Group.inverse(a5), Group.inverse(a6), Group.inverse(a7), Group.inverse(a8), Group.inverse(a9))
        }
    }

    instance Group[(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)] with Group[a1], Group[a2], Group[a3], Group[a4], Group[a5], Group[a6], Group[a7], Group[a8], Group[a9], Group[a10] {
        pub def inverse(x: (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)): (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) = match x {
            case (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) => (Group.inverse(a1), Group.inverse(a2), Group.inverse(a3), Group.inverse(a4), Group.inverse(a5), Group.inverse(a6), Group.inverse(a7), Group.inverse(a8), Group.inverse(a9), Group.inverse(a10))
        }
    }

}