An *endofunction* is a function where the parameter and return type are the same for instance *int* to *int*. It isn’t a very difficult concept but it is fun to play around with and see how functions compose. Below is a little example that builds on the last category theory post.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
package endomonoids trait Monoid[A]{ def op(a1: A, a2: A): A def id: A } object Main extends App { val intAddition: Monoid[Int] = new Monoid[Int] { def op(a1: Int, a2: Int) = a1 + a2 val id = 0 } val intMultiplication: Monoid[Int] = new Monoid[Int] { def op(a1: Int, a2: Int) = a1 * a2 val id = 1 } def endoMonoid: Monoid[Int => Int] = new Monoid[Int=>Int] { def op(a1: Int => Int, a2: Int => Int) = a1 compose a2 val id = (a: Int) => a } def endoMonoidAndThen: Monoid[Int => Int] = new Monoid[Int=>Int] { def op(a1: Int => Int, a2: Int => Int) = a1 andThen a2 val id = (a: Int) => a } println(s"endoMonoid.op(x => x+1, x => x+2)(3) is " + endoMonoid.op(x => x+1, x => x+2)(3)) println(s"endoMonoid.op(x => intMultiplication.op(x, x), x => intAddition.op(x, x)(5) is " + endoMonoid.op(x => intMultiplication.op(x, x), x => intAddition.op(x, x))(5)) println(s"endoMonoidAndThen.op(x => intMultiplication.op(x, x), x => intAddition.op(x, x)(5) is " + endoMonoidAndThen.op(x => intMultiplication.op(x, x), x => intAddition.op(x, x))(5)) } // endoMonoid.op(x => x+1, x => x+2)(3) is 6 // endoMonoid.op(x => intMultiplication.op(x, x), x => intAddition.op(x, x)(5) is 100 // endoMonoidAndThen.op(x => intMultiplication.op(x, x), x => intAddition.op(x, x)(5) is 50 |

Note there’s a bit of a design choice here that should reflect the semantic meaning of your program regarding the use of *andThen* or *compose*, but other than that endomonoid sounds like a way more difficult term than it turns out to be.