Fight the Future

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

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

One Div Zero: Monads are Elephants Part 3の翻訳。
今回からパート3。
偶然見つけた割には本当に良質の記事だと思います。モナドって説明読んでも全然わからない!って人は僕と一緒にこの記事読んで勉強していきましょう!

In this series I've presented an alternative view on the old parable about the blind men and the elephant. In this view, listening to the limited explanations from each of the blind men eventually leads to a pretty good understanding of elephants.

この連載では盲目の男たちと象の古い寓話への新しい観点を紹介しました。
盲目の男たちのそれぞれから限られた説明を聞くことで象へのとてもよい理解に至るということです。


So far we've been looking at the outside of monads in Scala. That's taken us a great distance, but it's time to look inside. What really makes an elephant an elephant is its DNA. Monads have a common DNA of their own in the form of the monadic laws.

これまでScalaにおけるモナドの外側を見てきました。それは深い理解をもたらしてくれましたが、ついに内側を見るときがきました。
象を象足らしめているものは何かというとDNAです。モナドモナド則の形式に独自の共通するDNAを持っています。


This article is a lot to digest all at once. It probably makes sense to read it in chunks. It can also be useful to re-read by substituting a monad you already understand (like List) into the laws.

この記事は一度にすべてを消化するためにとても長いものになっています。おそらくまとめて読まないと意味がわからないでしょう。
また(リストのように)すでに理解しているモナドに法則を適用しながら読み返すとよいでしょう。

Equality for All(すべてにとって等価である)

Before I continue, I have to semi-formally explain what I mean when I use triple equals in these laws as in "f(x) ≡ g(x)." What I mean is what a mathematician might mean by "=" equality. I'm just avoiding single "=" to prevent confusion with assignment.

続ける前に、「f(x) ≡ g(x)」のようにこれらの法則で私が3重等号を使うときに意味することをいくぶん形式的に説明しなければなりません。
意味することは数学者が「=」等号で意味することと同じです。ただの「=」を代入と混乱しないように避けているだけです。


So I'm saying the expression on the left is "the same" as the expression on the right. That just leads to a question of what I mean by "the same."

だから左辺と右辺が「等価」である式だと言っているわけです。これが「等価」によって意味することへの疑問を導きます。


First, I'm not talking about reference identity (Scala's eq method). Reference identity would satisfy my definition, but it's too strong a requirement. Second, I don't necessarily mean == equality either unless it happens to be implemented just right.

初めに、参照の同一(Scalaのeqメソッド)について話しているわけではありません。参照の同一は私の定義を満たすかもしれませんが、必要条件が強すぎます。
次に、偶然正しく実装されていない限り必ずしも==等式を意味していません。


What I do mean by "the same" is that two objects are indistinguishable without directly or indirectly using primitive reference equality, reference based hash code, or isInstanceOf.

「等価」が意味することは2つのオブジェクトが直接的にしろ間接的にしろプリミティブな参照の同一をやハッシュコードをベースにした参照、isInstanceOf使って区別できないということです。


In particular it's possible for the expression on the left to lead to an object with some subtle internal differences from the object on the right and still be "the same." For example, one object might use an extra layer of indirection to achieve the same results as the one on the right. The important part is that, from the outside, both objects must behave the same.

特に左辺の式が右辺のオブジェクトといくつかの微妙な内部的差異があるオブジェクトでありながらも「等価」であるということは考えられます。
たとえば、あるオブジェクトが右辺と同一の結果を達成するために外部の間接層を使うかもしれません。
重要なことは、外部から見れば両方のオブジェクトが同一のものとして振る舞わなければならないということです。


One more note on "the same." All the laws I present implicitly assume that there are no side effects. I'll have more to say about side effects at the end of the article.

「等価」でもう1つ注意することがある。暗黙的に示したすべての法則は副作用がないことを前提にしています。
この記事の最後で副作用についてもっと詳しく触れるつもりです。

Breaking the Law(法則を壊す)


Inevitably somebody will wonder "what happens if I break law x?" The complete answer depends on what laws are broken and how, but I want to approach it holistically first. Here's a reminder of some laws from another branch of mathematics. If a, b, and c are rational numbers then multiplication (*) obeys the following laws:

「もし法則xを壊すとどうなるのだろう?」と疑問に思う人が出てくるでしょう。
その完全な答えはどの法則をどのように壊したのかに依存しますが、まず総体的にアプローチします。
数学のもう1つの分野からの法則があることも思い出してください。
もしaとbとcが有理数であるならかけ算(*)は次の法則に従います。

  1. a * 1 ≡ a
  2. a * b ≡ b * a
  3. (a * b) * c ≡ a * (b * c)

Certainly it would be easy to create a class called "RationalNumber" and implement a * operator. But if it didn't follow these laws the result would be confusing to say the least. Users of your class would try to plug it into formulas and would get the wrong answers. Frankly, it would be hard to break these laws and still end up with anything that even looks like multiplication of rational numbers.

たしかに「RationalNumber」のようなクラスを作り*演算子を実装することは簡単です。
しかしもしこれらの法則に従わないなら結果は控えめに言っても混乱させられるものでしょう。
このクラスのユーザーは式にそれを利用して間違った答えを得るでしょう。
率直に言って、これらの法則を破ることは難しく、まだ有理数のかけ算のような何かでしかないでしょう。


Monads are not rational numbers. But they do have laws that help define them and their operations. Like arithmetic operations, they also have "formulas" that allow you to use them in interesting ways. For instance, Scala's "for" notation is expanded using a formula that depends on these laws. So breaking the monad laws is likely to break "for" or some other expectation that users of your class might have.

モナド有理数ではありません。しかしモナドとその演算を定義する助けとなる法則を持っています。
算術演算子のように、モナドもまた興味深い方法でそれらを使えるような「式」を持ちます。
たとえばScalaの「for」表記法はこれらの法則に依存した式を使って展開されます。
だからモナド則を破ることは「for」やそのクラスのユーザーが抱く期待を破る可能性があります。


Enough intro. To explain the monad laws, I'll start with another weird word: functor.

前置きはここまでです。モナド則を説明するために、もう1つの風変わりな単語ファンクターから始めます。