flix

0.77.0

SemiGroup.flix

/*
 *  Copyright 2021 Esben Bjerre
 *
 * Use of this source code is governed by the Apache 2.0 license
 * that can be found in the LICENSE.md file.
 */

///
/// Alias for `SemiGroup.combine`.
///
pub def ++(x: a, y: a): a with SemiGroup[a] = SemiGroup.combine(x, y)

pub mod SemiGroup {

    ///
    /// A trait for types that form a semigroup.
    ///
    pub trait SemiGroup[a] {
        ///
        /// An associative binary operation on `a`.
        ///
        pub def combine(x: a, y: a): a

        ///
        /// Returns `x` combined with itself `n` times.
        ///
        pub def combineN(x: a, n: Int32): a =
            if (n <= 1)
                x
            else
                SemiGroup.combine(x, SemiGroup.combineN(x, n - 1))
    }

    instance SemiGroup[Unit] {
        pub def combine(_: Unit, _: Unit): Unit = ()
    }

    instance SemiGroup[Int8] {
        pub def combine(x: Int8, y: Int8): Int8 = x + y
    }

    instance SemiGroup[Int16] {
        pub def combine(x: Int16, y: Int16): Int16 = x + y
    }

    instance SemiGroup[Int32] {
        pub def combine(x: Int32, y: Int32): Int32 = x + y
    }

    instance SemiGroup[Int64] {
        pub def combine(x: Int64, y: Int64): Int64 = x + y
    }

    instance SemiGroup[BigInt] {
        pub def combine(x: BigInt, y: BigInt): BigInt = x + y
    }

    instance SemiGroup[Float32] {
        pub def combine(x: Float32, y: Float32): Float32 = x + y
    }

    instance SemiGroup[Float64] {
        pub def combine(x: Float64, y: Float64): Float64 = x + y
    }

    instance SemiGroup[BigDecimal] {
        pub def combine(x: BigDecimal, y: BigDecimal): BigDecimal = x + y
    }

    instance SemiGroup[String] {
        pub def combine(x: String, y: String): String = x + y
    }

    instance SemiGroup[(a1, a2)] with SemiGroup[a1], SemiGroup[a2] {
        pub def combine(x: (a1, a2), y: (a1, a2)): (a1, a2) = match (x, y) {
            case ((x1, x2), (y1, y2)) => (SemiGroup.combine(x1, y1), SemiGroup.combine(x2, y2))
        }
    }

    instance SemiGroup[(a1, a2, a3)] with SemiGroup[a1], SemiGroup[a2], SemiGroup[a3] {
        pub def combine(x: (a1, a2, a3), y: (a1, a2, a3)): (a1, a2, a3) = match (x, y) {
            case ((x1, x2, x3), (y1, y2, y3)) => (SemiGroup.combine(x1, y1), SemiGroup.combine(x2, y2), SemiGroup.combine(x3, y3))
        }
    }

    instance SemiGroup[(a1, a2, a3, a4)] with SemiGroup[a1], SemiGroup[a2], SemiGroup[a3], SemiGroup[a4] {
        pub def combine(x: (a1, a2, a3, a4), y: (a1, a2, a3, a4)): (a1, a2, a3, a4) = match (x, y) {
            case ((x1, x2, x3, x4), (y1, y2, y3, y4)) => (SemiGroup.combine(x1, y1), SemiGroup.combine(x2, y2), SemiGroup.combine(x3, y3), SemiGroup.combine(x4, y4))
        }
    }

    instance SemiGroup[(a1, a2, a3, a4, a5)] with SemiGroup[a1], SemiGroup[a2], SemiGroup[a3], SemiGroup[a4], SemiGroup[a5] {
        pub def combine(x: (a1, a2, a3, a4, a5), y: (a1, a2, a3, a4, a5)): (a1, a2, a3, a4, a5) = match (x, y) {
            case ((x1, x2, x3, x4, x5), (y1, y2, y3, y4, y5)) => (SemiGroup.combine(x1, y1), SemiGroup.combine(x2, y2), SemiGroup.combine(x3, y3), SemiGroup.combine(x4, y4), SemiGroup.combine(x5, y5))
        }
    }

    instance SemiGroup[(a1, a2, a3, a4, a5, a6)] with SemiGroup[a1], SemiGroup[a2], SemiGroup[a3], SemiGroup[a4], SemiGroup[a5], SemiGroup[a6] {
        pub def combine(x: (a1, a2, a3, a4, a5, a6), y: (a1, a2, a3, a4, a5, a6)): (a1, a2, a3, a4, a5, a6) = match (x, y) {
            case ((x1, x2, x3, x4, x5, x6), (y1, y2, y3, y4, y5, y6)) => (SemiGroup.combine(x1, y1), SemiGroup.combine(x2, y2), SemiGroup.combine(x3, y3), SemiGroup.combine(x4, y4), SemiGroup.combine(x5, y5), SemiGroup.combine(x6, y6))
        }
    }

    instance SemiGroup[(a1, a2, a3, a4, a5, a6, a7)] with SemiGroup[a1], SemiGroup[a2], SemiGroup[a3], SemiGroup[a4], SemiGroup[a5], SemiGroup[a6], SemiGroup[a7] {
        pub def combine(x: (a1, a2, a3, a4, a5, a6, a7), y: (a1, a2, a3, a4, a5, a6, a7)): (a1, a2, a3, a4, a5, a6, a7) = match (x, y) {
            case ((x1, x2, x3, x4, x5, x6, x7), (y1, y2, y3, y4, y5, y6, y7)) => (SemiGroup.combine(x1, y1), SemiGroup.combine(x2, y2), SemiGroup.combine(x3, y3), SemiGroup.combine(x4, y4), SemiGroup.combine(x5, y5), SemiGroup.combine(x6, y6), SemiGroup.combine(x7, y7))
        }
    }

    instance SemiGroup[(a1, a2, a3, a4, a5, a6, a7, a8)] with SemiGroup[a1], SemiGroup[a2], SemiGroup[a3], SemiGroup[a4], SemiGroup[a5], SemiGroup[a6], SemiGroup[a7], SemiGroup[a8] {
        pub def combine(x: (a1, a2, a3, a4, a5, a6, a7, a8), y: (a1, a2, a3, a4, a5, a6, a7, a8)): (a1, a2, a3, a4, a5, a6, a7, a8) = match (x, y) {
            case ((x1, x2, x3, x4, x5, x6, x7, x8), (y1, y2, y3, y4, y5, y6, y7, y8)) => (SemiGroup.combine(x1, y1), SemiGroup.combine(x2, y2), SemiGroup.combine(x3, y3), SemiGroup.combine(x4, y4), SemiGroup.combine(x5, y5), SemiGroup.combine(x6, y6), SemiGroup.combine(x7, y7), SemiGroup.combine(x8, y8))
        }
    }

    instance SemiGroup[(a1, a2, a3, a4, a5, a6, a7, a8, a9)] with SemiGroup[a1], SemiGroup[a2], SemiGroup[a3], SemiGroup[a4], SemiGroup[a5], SemiGroup[a6], SemiGroup[a7], SemiGroup[a8], SemiGroup[a9] {
        pub def combine(x: (a1, a2, a3, a4, a5, a6, a7, a8, a9), y: (a1, a2, a3, a4, a5, a6, a7, a8, a9)): (a1, a2, a3, a4, a5, a6, a7, a8, a9) = match (x, y) {
            case ((x1, x2, x3, x4, x5, x6, x7, x8, x9), (y1, y2, y3, y4, y5, y6, y7, y8, y9)) => (SemiGroup.combine(x1, y1), SemiGroup.combine(x2, y2), SemiGroup.combine(x3, y3), SemiGroup.combine(x4, y4), SemiGroup.combine(x5, y5), SemiGroup.combine(x6, y6), SemiGroup.combine(x7, y7), SemiGroup.combine(x8, y8), SemiGroup.combine(x9, y9))
        }
    }

    instance SemiGroup[(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)] with SemiGroup[a1], SemiGroup[a2], SemiGroup[a3], SemiGroup[a4], SemiGroup[a5], SemiGroup[a6], SemiGroup[a7], SemiGroup[a8], SemiGroup[a9], SemiGroup[a10] {
        pub def combine(x: (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10), y: (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)): (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) = match (x, y) {
            case ((x1, x2, x3, x4, x5, x6, x7, x8, x9, x10), (y1, y2, y3, y4, y5, y6, y7, y8, y9, y10)) => (SemiGroup.combine(x1, y1), SemiGroup.combine(x2, y2), SemiGroup.combine(x3, y3), SemiGroup.combine(x4, y4), SemiGroup.combine(x5, y5), SemiGroup.combine(x6, y6), SemiGroup.combine(x7, y7), SemiGroup.combine(x8, y8), SemiGroup.combine(x9, y9), SemiGroup.combine(x10, y10))
        }
    }

    pub enum Any(Bool)

    instance SemiGroup[Any] {
        pub def combine(x: Any, y: Any): Any = match (x, y) {
            case (Any.Any(a), Any.Any(b)) => Any.Any(a or b)
        }
    }

    instance Monoid[Any] {
        pub def empty(): Any = Any.Any(false)
    }

    instance CommutativeMonoid[Any]

    pub enum All(Bool)

    instance SemiGroup[All] {
        pub def combine(x: All, y: All): All = match (x, y) {
            case (All.All(a), All.All(b)) => All.All(a and b)
        }
    }

    instance Monoid[All] {
        pub def empty(): All = All.All(true)
    }

    instance CommutativeMonoid[All]

}