Scala with Cats を読んだので学習した内容のメモを残します。
2章のMonoids and Semigroupsです。
はじめに
Monoidは二項演算と単位元を持つ代数的構造であり、Catsでは型クラスが提供されている。
Monoidの定義
CatsでのMonoidの定義を簡略化したものが以下。
trait Monoid[A] { def combine(x: A, y: A): A def empty: A }
- combine(二項演算): A型の2つの値を結合させて1つのA型の値を返す
- empty(単位元): A型の空要素を返す
という2つの操作がMonoidには定義されている。
combineとemptyの操作に加えて、Monoidはいくつかの法則に従う必要がある。
def associativeLaw[A](x: A, y: A, z: A)(implicit m: Monoid[A]): Boolean = { m.combine(x, m.combine(y, z)) == m.combine(m.combine(x, y), z) } def identityLaw[A](x: A)(implicit m: Monoid[A]): Boolean = { (m.combine(x, m.empty) == x) && (m.combine(m.empty, x) == x) }
例えば整数の足し算、整数の掛け算、文字列の連結はこれらの法則に従うが、整数の引き算は従わない。
Semigroupの定義
SemigroupはMonoidのcombineの部分であり、emptyは含まない。
trait Semigroup[A] { def combine(x: A, y: A): A } trait Monoid[A] extends Semigroup[A] { def empty: A }
CatsにおけるMonoid
Monoid型クラスは cats.kernel.Monoid
で、cats.Monoid
としてエイリアスされている。
catsパッケージから型クラスをimportする
import cats.Monoid import cats.Semigroup
instance
import cats.Monoid import cats.instances.string._ // for Monoid Monoid[String].combine("Hi ", "there") // res0: String = "Hi there" Monoid[String].empty // res1: String = ""
個々のinstanceをimportする理由がなければ全てをimportすればいい。
import cats._ import cats.implicits._
syntax
Catsは、|+|
演算子の形でcombineメソッドの構文を提供している。
Monoidの活用例
(1)ビッグデータ
SparkやHdoopのようなアプリケーションで複数マシンでの計算結果を組み合わせる
(2)分散システム
2つのデータをマージする際、この操作はMonoidであることに依存している
まとめ
Semigroupは加算や組み合わせの演算を表し、MonoidはSemigroupに恒等要素や ゼロ 要素を追加して拡張したもの