ぶろぐ

日記です

Monoidを使ってみた


Semigroup(半群)に単位元を加えたものがMonoid(単位的半群)。Semigroupは結合法則を持つ。

ざっくり言うと「足し算のやり方と、ゼロはなんだ?」というのを持っていればMonoid。

import scalaz._
import Scalaz._

object HelloMonoid extends App {

  case class Hoge(cost: Int, cv: Int)

  implicit object HogeMonoid extends Monoid[Hoge] {
    def zero: Hoge = Hoge(0, 0)
    def append(r1: Hoge, r2: => Hoge): Hoge = Hoge(r1.cost + r2.cost, r1.cv + r2.cv)
  }

  Console println Hoge(100, 2) |+| Hoge(50, 3)
  //Hoge(150,5)

  val hs = Hoge(100, 2) :: Hoge(200, 3) :: Nil

  Console println hs.reduce(_ |+| _)
  //Hoge(300,5)

  Console println hs.foldLeft(HogeMonoid.zero)(_ |+| _)
  //Hoge(300,5)


  case class Foo(s: String, xs: List[Int])

  implicit object FooMonoid extends Monoid[Foo] {
    def zero: Foo = Foo("", List.empty)
    def append(r1: Foo, r2: => Foo): Foo = Foo(s"${r1.s} and ${r2.s}", r1.xs ::: r2.xs)
  }

  val fs = Foo("apple", List(1, 2)) :: Foo("ornge", List(5, 9)) :: Foo("banana", List(0)) :: Nil

  Console println fs.reduce(_ |+| _)
  //Foo(apple and ornge and banana,List(1, 2, 5, 9, 0))
}