/* From notes of meeting with Alex Stepanov */ include_c "stdlib.h"; use "basic_concepts.g"; concept BinaryOperation { fun apply(Op, T, T) -> T@; }; concept UnaryFunction { fun apply(Op, T) -> R@; }; concept Semigroup_ { refines BinaryOperation; /* axiom Associativity(T x, T y, T z, Op op) { assert(op(x, op(y, z)) == op(op(x, y), z)); } */ }; concept Monoid_ { refines Semigroup_; fun identity_element(Op) -> T; /* axiom Identity(Op op, T x) { T id(identity_element(op)); assert(op(id, x) == x); assert(op(x, id) == x); } */ }; concept Group { refines Monoid_; type inverse_t; require UnaryFunction; fun inverse(Op) -> inverse_t@; /* axiom Invertibility(Op op, T x, Ty) { T id(identity_element(op)); assert(op(inverse(op)(x), x) == id); assert(op(x, inverse(op)(x)) == id); } */ }; fun left_power where { Regular, SignedIntegral, BinaryOperation } (T@ a, I@ n, Op op) -> T@ { let result = a; while (--n != zero()) result = apply(op, result, a); return result; } fun power_semigroup where { Regular, SignedIntegral, Semigroup_ } (T a, I n, Op op) -> T@ { /*assert(n > zero());*/ return left_power(a, n, op); } fun power_monoid where { Regular, SignedIntegral, Monoid_ } (T a, I n, Op op) -> T@ { /*assert(n >= 0);*/ if (n == zero()) return identity_element(op); else { return power_semigroup(a, n, op); } } fun power_group where { Regular, SignedIntegral, Group } (T a, I n, Op op) -> T@ { if (n < zero()) return power_group(apply(inverse(op), a), -n, op); else { return power_monoid(a, n, op); } } fun power where { Regular, SignedIntegral, Semigroup_ } (T a, I n, Op op) -> T@ { return power_semigroup(a, n, op); } fun power where { Regular, SignedIntegral, Monoid_ } (T a, I n, Op op) -> T@ { return power_monoid(a, n, op); } fun power where { Regular, SignedIntegral, Group } (T a, I n, Op op) -> T@ { return power_group(a, n, op); } fun main() -> int@ { /* add models and a call to power... */ return 0; }