role Semigroup[::T] {
method append(T $a, T $b --> T) {!!!}
}
role Monoid[::T] does Semigroup[T] {
method empty(--> T) {!!!}
}
role Group[::T] does Monoid[T] {
method inverse(T $a --> T) {!!!}
}
class IntAdd does Group[Int] {
method append(Int $a, Int $b --> Int) { $a + $b }
method empty(--> Int) { 0 }
method inverse(Int $a --> Int) { -$a }
}
class IterableCat does Monoid[Iterable] {
method append(Iterable $a, Iterable $b --> Iterable) { (|$a, |$b) }
method empty(--> Iterable) { () }
}
sub concat(Monoid $m, @xs) {
($m.empty, |@xs).reduce: {$m.append($^a, $^b)};
}
dd concat(IntAdd, [1, 2, 3]);
dd concat(IntAdd, [1, 2]);
dd concat(IntAdd, [1]);
dd concat(IntAdd, []);
dd concat(IterableCat, [<1 2 3>, <4 5 6>, <7 8 9>]);
dd concat(IterableCat, [<1 2 3>, <4 5 6>]);
dd concat(IterableCat, [<1 2 3>,]);
dd concat(IterableCat, []);