9

「ProgramminginScala2nd Edition」を読んでいて、私が受講したHaskellコースのモナドについていくつか考えています。ただし、次のコードが「魔法のように」機能する理由がわかりません。

scala> val a: Option[Int] = Some(100)
a: Option[Int] = Some(100)

scala> val b = List(1, 2, 3)
b: List[Int] = List(1, 2, 3)

for ( y <- b; x <- a ) yield x;
res5: List[Int] = List(100, 100, 100)

本の第23.4章によると、for表現は次のように翻訳されているので、私は上記を理解していません。

b flatMap ( y =>
  a map ( x => x )
)

y => a map (x => x)が型Int => Option[Int]であるために上記のコードがコンパイルされる理由に戸惑いますが、は。をb.flatMap期待していInt => List[Something]ます。

一方、次のコードはコンパイルされません(これは良いことです。さもないと私はもっと失われてしまいます):

scala> for ( x <- a; y <- b ) yield y;
<console>:10: error: type mismatch;
 found   : List[Int]
 required: Option[?]
              for ( x <- a; y <- b ) yield y;
                          ^

では、最初の例の魔法は何ですか?

4

1 に答える 1

8

[…]は。b.flatMapを期待しInt => List[Something]ます。

それは真実ではありません:それが期待するのはですInt => GenTraversableOnce[Something]。(http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.Listを参照し、ページで。を検索してくださいflatMap。)は継承によるList[A]のサブタイプです。GenTraversableOnce[A]タイプの関数は、の結果のInt => List[Something]共分散のために置換することができます。これは、次のように定義されます。RFunction1trait Function1[-T1, +R]

Option[A]はではありませんが、 OptionのコンパニオンオブジェクトGenTraversableOnce[A]に暗黙の変換があります: 。のサブタイプです。したがって、for-expressionは次のように展開されますimplicit def option2Iterable[A](xo: Option[A]): Iterable[A]Iterable[A]GenTraversableOnce[A]

b flatMap ( y =>
  option2Iterable(a map ( x => x ))
)

一方、次のコードはコンパイルされません[…]

これはa.flatMap、対照的に、より具体的であるためです。実際には。が必要ですInt => Option[Something]。(http://www.scala-lang.org/api/current/index.html#scala.Optionを参照し、ページで検索してくださいflatMap。)これは理にかなっています。これは、Option[Something]が1つの値しか保持できないため、保持できないためです。それに任意のものを平らGenTraversableOnce[Something]にします。に正常に平坦化できる唯一のものOption[Something]は別のものOption[Something]です。

于 2013-02-24T03:23:04.830 に答える