Fight the Future

Java言語とJVM、そしてJavaエコシステム全般にまつわること

モナドについて調べていく(19)

One Div Zero: Monads are Elephants Part 3の翻訳続き。

The First Monad Law: Identity(第一のモナド則:同一性)


The first and simplest of the monad laws is the monad identity law

モナド則の最初の、そしてもっとも単純な法則はモナドの同一性の法則です。

  • M1. m flatMap unit ≡ m // or equivalently
  • M1a. m flatMap {x => unit(x)} ≡ m

Where the connector law connected 3 concepts, this law focuses on the relationship between 2 of them. One way of reading this law is that, in a sense, flatMap undoes whatever unit does. Again the reminder that the object that results on the left may actually be a bit different internally as long as it behaves the same as "m."

結合法則が3つの概念をつなげているのに対して、この法則はそのうち2つの関係に焦点を合わせています。この法則を読み解く1つの方法は、ある意味ではflatMapはunitが行ったことを元に戻しているだけです。もう1度思い出してほしいのが左辺の結果となるオブジェクトは実はそれが「m」として同じように振る舞う限り内部的に少し異なっているかもしれないということです。


Using this and the connection law, we can derive the functor identity law

これと結合法則を使ってファンクターの同一法則を導出することができます。

  • m flatMap {x => unit(x)} ≡ m // M1a
  • m flatMap {x => unit(identity(x))}≡ m // identity
  • F1b. m map {x => identity(x)} ≡ m // by FM1
jyukutyoコメント

ファンクターの第1法則は「m map identity ≡ m」。map {x => identity(x)} と map identity は等価。


The same derivation works in reverse, too. Expressed in "for" notation, the monad identity law is pretty straight forward

同じ導出は逆からでも有効です。「for」表記法で表せば、モナドの同一法則はとても明白です。

  • M1c. for (x <- m; y <- unit(x)) yield y ≡ m

The Second Monad Law: Unit(モナドの第2法則:Unit)


Monads have a sort of reverse to the monad identity law.

モナドの同一法則に対するある種の逆法則もあります。

  • M2. unit(x) flatMap f ≡ f(x) // or equivalently
  • M2a. unit(x) flatMap {y => f(y)} ≡ f(x)

The law is basically saying that unit(x) must somehow preserve x in order to be able to figure out f(x) if f is handed to it. It's in precisely this sense that it's safe to say that any monad is a type of container (but that doesn't mean a monad is a collection!).

この法則は基本的に次のようなことを言っています。もしfがxを扱うなら、f(x)を算定できるようにするためにunit(x)はなんとかしてxを保存しなければならないということです。
正確にこの意味においてあらゆるモナドはコンテナ型であると言っても安全です(しかしこれはモナドがコレクションであるとは言っていません!)。


In "for" notation, the unit law becomes

「for」表記法では、unit法則はこうなります。

  • M2b. for (y <- unit(x); result <- f(y)) yield result ≡ f(x)

This law has another implication for unit and how it relates to map

この法則はunitについてそれがどのようにmapと関連するかということも暗示します。

  1. unit(x) map f ≡ unit(x) map f // no, really, it does!
  2. unit(x) map f ≡ unit(x) flatMap {y => unit(f(y))} // by FM1
  3. M2c. unit(x) map f ≡ unit(f(x)) // by M2a

In other words, if we create a monad instance from a single argument x and then map it using f we should get the same result as if we had created the monad instance from the result of applying f to x. In for notation

言い換えると、もし単一引数xでモナドインスタンスを生成しそれをfを使ってmapすると、xにfを適用した結果からモナドを生成したときと同じ結果を得るべきです。
for表記法では、

  • M2d. for (y <- unit(x)) yield f(y) ≡ unit(f(x))

The Third Monad Law: Composition(モナド第3法則:コンポジション)

The composition law for monads is a rule for how a series of flatMaps work together.

モナドにとってのコンポジション法則は一連のflatMapがどのように一緒に動作するかのルールです。

  • M3. m flatMap g flatMap f ≡ m flatMap {x => g(x) flatMap f} // or equivalently
  • M3a. m flatMap {x => g(x)} flatMap {y => f(y)} ≡ m flatMap {x => g(x) flatMap {y => f(y) }}

It's the most complicated of all our laws and takes some time to appreciate. On the left side we start with a monad, m, flatMap it with g. Then that result is flatMapped with f. On the right side, we create an anonymous function that applies g to its argument and then flatMaps that result with f. Finally m is flatMapped with the anonymous function. Both have same result.

これはすべての法則の中でもっとも複雑であり、認めるには時間がかかります。左辺ではモナドmで始めそれをgでflatMapします。それからその結果をfでflatMapします。
右辺では引数にgを適用しその結果をfでflatMapする無名関数を作成します。結局mは無名関数でflatMapされます。
両方とも同じ結果になります。


In "for" notation, the composition law will send you fleeing in terror, so I recommend skipping it

「for」表記法ではコンポジション法則は恐れをなして逃げてしまいそうなので、飛ばすことをお勧めします。

  • M3b. for (a <- m;b <- g(a);result <- f(b)) yield result ≡ for(a <- m; result <- for(b < g(a); temp <- f(b)) yield temp) yield result

From this law, we can derive the functor composition law. Which is to say breaking the monad composition law also breaks the (simpler) functor composition. The proof involves throwing several monad laws at the problem and it's not for the faint of heart

この法則から、ファンクターのコンポジション法則を導出できます。それはモナドのコンポジション法則を破ると同時に(より単純な)ファンクターのコンポジションも破ることになるということです。証明はいくつかのモナド則を問題に投入することを含んでいますが、気弱な人は見なくても結構です。

  1. m map g map f ≡ m map g map f // I'm pretty sure
  2. m map g map f ≡ m flatMap {x => unit(g(x))} flatMap {y => unit(f(y))} // by FM1, twice
  3. m map g map f ≡ m flatMap {x => unit(g(x)) flatMap {y => unit(f(y))}} // by M3a
  4. m map g map f ≡ m flatMap {x => unit(g(x)) map {y => f(y)}} // by FM1a
  5. m map g map f ≡ m flatMap {x => unit(f(g(x))} // by M2c
  6. F2. m map g map f ≡ m map {x => f(g(x))} // by FM1a

Total Loser Zeros(完全な敗者はいない)


List has Nil (the empty list) and Option has None. Nil and None seem to have a certain similarity: they both represent a kind of emptiness. Formally they're called monadic zeros.

リストはNil(空のリスト)を持ちOptionはNoneを持っています。NilとNoneにはある類似性があります。両方ともある種の空を表しています。正式にはモナド的なゼロと呼ばれるものです。


A monad may have many zeros. For instance, imagine an Option-like monad called Result. A Result can either be a Success(value) or a Failure(msg). The Failure constructor takes a string indicating why the failure occurred. Every different failure object is a different zero for Result.

モナドは多くのゼロを持っているかもしれません。例えばResultと呼ぶOptionのようなモナド想像してみてください。ResultはSuccess(value) かFailure(msg)のどちらかです。Failureのコンストラクタはなぜ失敗が起こったかを示す文字列を引数に取ります。すべての異なるfailureオブジェクトはResultにとって異なるゼロとなります。


A monad may have no zeros. While all collection monads will have zeros (empty collections) other kinds of monads may or may not depending on whether they have a concept of emptiness or failure that can follow the zero laws.

モナドはゼロを持たないかもしれません。すべてのコレクションモナドはゼロ(空のコレクション)を持ちますが、他の種類のモナドはゼロの法則に従う空や失敗の概念に依存するかもしれませんし、しないかもしれません。

The First Zero Law: Identity(第1のゼロの法則:同一性)


If mzero is a monadic zero then for any f it makes sense that

もしmzeroがモナド的なゼロであればあらゆるfの場合で次のことが成り立ちます。

  • MZ1. mzero flatMap f ≡ mzero

Translated into Texan: if t'ain't nothin' to start with then t'ain't gonna be nothin' after neither.

テキサスなまりに変換しましょう。もし???


This law allows us to derive another zero law

この法則はほかのゼロの法則を導出します。

  1. mzero map f ≡ mzero map f // identity
  2. mzero map f ≡ mzero flatMap {x => unit(f(x)) // by FM1
  3. MZ1b. mzero map f ≡ mzero // by MZ1

So taking a zero and mapping with any function also results in a zero. This law makes clear that a zero is different from, say, unit(null) or some other construction that may appear empty but isn't quite empty enough. To see why look at this

ゆえにゼロにどんな関数をmapしても結果はゼロになります。この法則は次のことを明らかにします。ゼロはunit(null)や空のように見えるが完全に空ではない他の構造とは異なるということです。なぜなのか見てみましょう。

  • unit(null) map {x => "Nope, not empty enough to be a zero"} ≡ unit("Nope, not empty enough to be a zero")