fugafuga.write

日々のログ

すごいH本 part79

Monoid 大集合

以下のような共通の性質をもつ関数が存在する。

  • 関数は引数を2つとる
  • 2つの引数および返り値の型はすべて等しい
  • 2引数関数を施して相手を変えないような特殊な値が存在する
    • ++ なら空リスト
    • * なら 1
    • 例: x * 1, "hoho" ++ []

*Main> (3 * 2) * (8 * 5)
240
*Main> 3 * (2 * (8 * 5))
240
*Main> "la" ++ ("di" ++ "ga")
"ladiga"
*Main> ("la" ++ "di") ++ "ga"
"ladiga"

この性質を 結合的(associativity) という。 ++* が当てはまる。

- は当てはまらない。

*Main> (5 - 3) - 4
-2
*Main> 5 - (3 - 4)
6

Monoid 型クラス

モノイドは、結合的な二項演算子(2引数関数) と、その演算に関する単位元からなる構造である。

ある値がある演算の単位元である。とは、 その値となにか他の値を引数にしてその演算を呼び出した時、 返り値が常に他の値のほうに等しくなる。 ということ

  • 1* の単位元である。
  • []++ の単位元である。

以下は Monoid の定義

class Monoid m where
    mempty :: m
    mappend :: m -> m -> m
    mconcat :: [m] -> m
    mconcat = foldr mappend mempty

Monoid のインスタンスになれるのは具体型のみ

mempty は、そのモノイドの単位元を表す。

mappend は、モノイド固有の二項演算。 同じ型の引数を2つ取り、その型の別の値を返す。 append という関数名から連想される付け加えるというイメージは捨てること。

mconcat は、モノイドのリストをとって、mappend を間に挟んだ式を作り、 単一の値を計算してくれる関数。 デフォルト実装がついており、たいていの場合これで事足りる。

自分で Monoid型クラスのインスタンスを作るときも、 memptymappend だけ実装すればだいたい動く。

モノイド則

Monoid インスタンスは次の法則を満たさなければならない

1

mempty `mappend` x = x

2

x `mappend` mempty = x

3

(x `mappend` y) `mappend` z = x `mappend` (y `mappend` z)

1つ目と2つ目は、memptymappend に関して単位元として振る舞う必要があることを述べている。 3つ目は、mappend が結合的であることを述べている。

所感

いきなり単位元という言葉が登場して面食らったが、 ファンクターと同じようにこういう構造を持ったデータ型を作りたい時に使うんだな。たぶん。 モノイド を使うとなにが嬉しいのかはこれからわかるのであろう。

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!

  • 作者: MiranLipovaca
  • 出版社/メーカー: オーム社
  • 発売日: 2017/07/14
  • メディア: Kindle版
  • 購入: 4人 クリック: 9回
  • この商品を含むブログを見る