モナドはコンテナだ。リラックマもコンテナ(中身入ってるし)だ。
だったら、モナドはリラックマだ。
と言う訳で、リラックマでモナド則書いてみた。
まず、リラックマの実装。リラックマは、皮と中身がある。そもそもいない時もある。
まさにMaybeだ。なので、Optionにしてみる。
えぇ手抜きですとも。
val リラックマ = Option
んじゃ、最初のモナド則。
(return x)は何かを渡されるとモナドにして返してくれるものなので、 リラックマ製造機として定義する。中の人を渡すとリラックマにしてくれる。
def リラックマ製造機[a] = (x:a) => リラックマ(x)
次に、fを定義。 名状しがたい何かを渡すと中身を本物にしてくれる。
def f[a] = (x:a) => リラックマ("ニャルラトホテプ")
試しに呼び出してみると
f("ニャル子さん") == リラックマ("ニャルラトホテプ")
res0: Boolean = true
ほら、本物になった。
">>="は混沌としたscala界ではflatMapに変換される。
(リラックマ製造機("ニャル子さん") flatMap f) == f("ニャル子さん")
res1: Boolean = true
検証完了。
mはモナドだからリラックマに置き換える。
(リラックマ("ニャル子さん") flatMap リラックマ製造機) == リラックマ("ニャル子さん")
res2: Boolean = true
検証完了。
次に関数gを定義する。 リラックマの中の人を増殖させる関数。使い方を誤ると恐ろしい事が起きる。
def g[a] = (x:a) => リラックマ(x :: List(x))
g("おっさん")
res3: Option[List[String]] = Some(List(おっさん, おっさん))
キャー
val l = (リラックマ("ニャル子さん") flatMap f) flatMap g
val r = リラックマ("ニャル子さん") flatMap {x => f(x) flatMap g}
l==r
…なんか本物増えてるけど… まぁいいや。検証完了。
これで、モナドがリラックマである事が証明された。 めでたしめでたし。
Optionなんだから満たして当たり前とか言わないで(´・ω・`)