2011年12月4日日曜日

Semigroup, Zero, Monoid

今日はSemigroupでゲソ!

この記事は

Functional Ikamusume Advent Calendar jp 2011



一人Scalaz Advent Calendar

を兼ねているんじゃなイカ!?


Semigroup

Semigroupは結合可能という性質を表すでゲソ。

Semigroupは関数 def append(s1: S, s2: => S): S を持ち、2つの値から一つの結果を得る関数を持つでゲソ。

Semigroupのインスタンスはsemigroup関数を使うことで定義できるんじゃなイカ?

Semigroups#semigroup

case class Ikamusume(syokusyu: Int = 10)
implicit def IkamusumeEqual: Equal[Ikamusume] = equalA
implicit def IkamusumeShow: Show[Ikamusume] = shows("ゲソ" * _.syokusyu)
implicit def IkamusumeSemigroup: Semigroup[Ikamusume] = semigroup(_.syokusyu + _.syokusyu |> Ikamusume)
(Ikamusume() |+| Ikamusume()).shows assert_=== "ゲソゲソゲソゲソゲソゲソゲソゲソゲソゲソゲソゲソゲソゲソゲソゲソゲソゲソゲソゲソ"

Semigroupを利用する関数

|+|

加算だけでなく、型によって様々な動きをするでゲソ。

1 |+| 1 assert_=== 2
List(1) |+| List(1) assert_=== List(1, 1)
"Hello" |+| "World" assert_=== "HelloWorld"
1.some |+| 1.some assert_=== 2.some
false |+| true assert_=== true

加算や連結、論理和のような動きをするでゲソ。
===と同様に型安全でもあるでゲソ!

・・・・・Semigroup単体だとこれだけでゲソ。

あまりにも寂しいのでZero, Monoidまでやろうじゃなイカ!

Zero

Zeroは単位元を表すでゲソ。

mzero

mzeroは型パラメータを取り、その型の単位元を返すでゲソ。
mzero[Int] assert_=== 0
mzero[String] assert_=== ""
mzero[List[Int]] assert_=== nil[Int]
mzero[Option[Int]] assert_=== none[Int]
view raw zero1.scala hosted with ❤ by GitHub

matchOrZero

matchOrZeroは型パラメータとPartialFunctionを取り、マッチしない場合はその型の単位元を返すでゲソ!

lazy val geso: Option[Int] => String = _.matchOrZero {
case Some(n) => "ゲソ" * n
}
geso(2.some) assert_=== "ゲソゲソ"
geso(none) assert_=== ""
view raw zero3.scala hosted with ❤ by GitHub

Zeros#zero

Zeroのインスタンスはzeroにより定義できるんじゃなイカ?

implicit def IkamusumeZero: Zero[Ikamusume] = zero(Ikamusume(0))
mzero[Ikamusume].shows assert_=== ""
view raw zero2.scala hosted with ❤ by GitHub

そして、SemigroupとZeroを兼ね備えたものがMonoidなのでゲソ!

Monoid

MonoidはSemigroupとZeroを継承したものでゲソ。

Monoidは

forall a. append(zero, a) == a

forall a. append(a, zero) == a

を満たすのでゲソ。

def check[A: Equal: Show: Monoid](a: A) = {
a |+| mzero[A] assert_=== a
mzero[A] |+| a assert_=== a
}
check(1)
check("Scalaz")
check(List(1, 2, 3))
check(Ikamusume())
view raw monoid1.scala hosted with ❤ by GitHub

イカ娘も立派なモノイドじゃなイカ?

Monoid単体を利用する関数はほとんどないのでゲソ。
Monoidは他の型クラスと一緒に使うことが多いのでその時に紹介しようじゃなイカ!

0 件のコメント:

コメントを投稿