はじめに

Data.MonoidEndo 型が定義されています。

Endo という名前は 自己準同型 (Endomorphism) に由来します。

使い方は簡単。

appEndo すると関数が出てくるところがポイントですね。2つ目の評価の流れをざっくり追うとこんな感じです。

  appEndo (Endo ("Hello, " ++) <> Endo (++ "!")) "Haskell"
= appEndo (Endo (("Hello, " ++ ) . (++ "!"))) "Haskell"
= ("Hello, " ++ ) . (++ "!") $ "Haskell"
= "Hello, " ++ ("Haskell" ++ "!")
= "Hello, " ++ "Haskell!"
= "Hello, Haskell!"

Endo は意外と色んなところで使える便利なモノイドです。

Semigroup, Monoid law の確認

Semigroup Law

Monoid Law

f . (g . h) == (f . g) . h

(.) の定義

証明

id . f == f

id の定義

証明

例1) Write Endo パターン

yesod-core パッケージの ProvideRep を扱う関数は Endo を利用しています。

また Yesod には GHState 型がありますが、そこでも Endo を使っています。

このような WriterEndo を使った実装パターンは Quick and Easy DSLs with Writer Endo で紹介されている Writer Endo パターンとして知られているようです。

例2) データの更新

こんな感じで設定等を更新する際にも使えるかもしれません。

実行結果

例3) パターンマッチの実装

僕はあまり Endo モノイドを使いこなせていませんが、良い感じに使えたと思える例としては TAPL 11章でレコードパターンを実装する際です。

レコードのパターンマッチは代入の合成で書くことができるので、Endo がちょうどぴったり適用できました。

参考