ふと気になったけど今まで記事書いてなかったのでいちおう確かめることにした。
ある1引数関数f: A => B
があったとする。
type A type B val f: A => B = ???
B
がモノイドであるとする。
implicit class BMonoid extends Monoid[B] { ... }
このとき、1引数関数A => B
(Function1[A, B]
)はモノイドになるだろうか?
なります
結論から言うと、モノイドになる。
これは、cats.kernel.instances.Function1Monoid
が定義されているため。
final private[instances] case class CombineFunction1[A, B](left: A => B, right: A => B, semiB: Semigroup[B]) extends (A => B) { private def call(fn: A => B, a: A): TailRec[B] = fn match { case ref: CombineFunction1[A, B] @unchecked => for { lb <- tailcall(call(ref.left, a)) rb <- tailcall(call(ref.right, a)) } yield ref.semiB.combine(lb, rb) case _ => done(fn(a)) } final override def apply(a: A): B = call(this, a).result } trait Function1Semigroup[A, B] extends Semigroup[A => B] { implicit def B: Semigroup[B] override def combine(x: A => B, y: A => B): A => B = CombineFunction1(x, y, B) override def combineAllOption(fns: IterableOnce[A => B]): Option[A => B] = if (fns.iterator.isEmpty) None else Some { (a: A) => B.combineAllOption(fns.iterator.map(_.apply(a))).get } } trait Function1Monoid[A, B] extends Function1Semigroup[A, B] with Monoid[A => B] { implicit def B: Monoid[B] val empty: A => B = (_: A) => B.empty }
要するに、同じ引数を渡して、その結果はモノイドなのでcombine
する、というだけ。
振る舞いとしても自然だし、なにかと役立つだろう。