web-dev-qa-db-ja.com

OptionがScalaのモナドになるのは何ですか?

私はモナドとは何か、そしてそれらの使い方を知っています。 whatOptionをモナドにしたとしましょう。

Haskellでは、モナドMaybeはモナドです。これは、Monadクラスからインスタンス化されているためです(クラスには、returnbindがあり、クラスMonad、実際にはモナドになります)。

しかし、Scalaにはこれがあります:

sealed abstract class Option[+A] extends Product with Serializable { ... }
trait Product extends Any with Equals { ... }

モナドに関連するものはありません。

Scalaで独自のクラスを作成すると、デフォルトでモナドになりますか?何故なの?

36
アレックス

Monadは、データの構成方法を単純に定義する概念であり、抽象インターフェースです。

Optionは、flatMapによる構成をサポートします。これが、「モナドバッジ」の着用に必要なほとんどすべての機能です。

理論的な観点から、次のことも行う必要があります。

  • unit操作(Haskell用語ではreturn)をサポートして、裸の値からモナドを作成します。これは、Optionの場合はSomeコンストラクタです。
  • モナドの法則を尊重する

しかし、これはScalaによって厳密に強制されているわけではありません。

scalaのモナドは、Haskellの場合よりもはるかに緩やかな概念であり、アプローチがより実用的です。言語の観点から、モナドが関連するのは、forで使用される機能だけです。 -理解。

flatMapは基本的な要件であり、オプションでmapwithFilterforeachを指定できます。

ただし、HaskellのようにMonad型クラスに厳密に準拠するようなものはありません。

次に例を示します。独自のモナドを定義しましょう。

class MyMonad[A](value: A) {
  def map[B](f: A => B) = new MyMonad(f(value))
  def flatMap[B](f: A => MyMonad[B]) = f(value)
  override def toString = value.toString
}

ご覧のとおり、mapflatMapだけを実装しています(まあ、toStringを商品として)。おめでとう、モナドができました!試してみましょう:

scala> for {
  a <- new MyMonad(2)
  b <- new MyMonad(3)
} yield a + b
// res1: MyMonad[Int] = 5

いいね!フィルタリングは行わないため、withFilterを実装する必要はありません。また、値を生成しているので、foreachも必要ありません。基本的に、厳密な要件なしに、サポートしたいものをすべて実装します。 for内包でフィルターをかけようとしていて、withFilterを実装していない場合は、コンパイル時エラーが発生します。

59

FilterMonadic トレイトがダックタイピングによって(部分的に)実装されるものはすべて、Scalaのモナドと見なされます。これは、Haskellでモナドを表現する方法、または Monad scalazのtypeclass とは異なります。ただし、Scalaのfor内包構文糖度を利用するには、オブジェクトがFilterMonadic特性で定義されているメソッドの一部を公開する必要があります。

また、Scalaでは、Haskellのreturn関数に相当するものは、yield内包から値を生成するために使用されるforキーワードです。 yieldの脱糖は、「モナド」のmapメソッドの呼び出しです。

13
Ionuț G. Stan

私の言い方では、モナドの間には設計パターンファーストクラスの抽象化の違いが浮上しています。 HaskellにはMonad型クラスの形式で後者があります。しかし、モナド演算を持ち(または実装できる)型があり、法則に従う場合、それもモナドです。

最近では、モナドをJava 8's librariesの設計パターンとして見ることができます。OptionalStreamはJava 8には、Haskell ofに対応する静的returnメソッドとflatMapメソッドがありますが、Monadタイプはありません。

Ionuț G. Stanの回答が示すように、あなたの間のどこかに「アヒル型」アプローチがあります。 C#にもこれがあります。LINQ構文は特定の型に関連付けられていませんが、特定のメソッドを実装する任意のクラスで使用できます。

9
Luis Casillas