2013-02-24 2 views
9

私は「Programming in Scala 2nd Edition」を読んでいます。私が取ったハスケルコースからモナドについて考えています。複数のモナドを持つfor式をscalaでどのように変換しますか?

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)がのタイプであり、b.flatMapInt => 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; 
         ^

それでは、最初の例と魔法のですか?

答えて

8

[&hellip;] 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]の関数は、RFunction1の共分散のために次のように定義されます。trait Function1[-T1, +R]のように定義されます。

Option[A]GenTraversableOnce[A]ではありませんが、Option's companion objectimplicit def option2Iterable[A](xo: Option[A]): Iterable[A]に暗黙の変換があります。 Iterable[A]はサブタイプGenTraversableOnce[A]です。だから、のための表現一方

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

に展開されます、次のコードはコンパイルされません[&hellip;]

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]です。

+0

'Option'は' GenTraversableOnce'ではありません –

+0

Optionオブジェクトに定義されているoption2Iterableという暗黙的な変換があり、これはOptionをIterableに変換することができます。 – Eastsun

+0

@LuigiPlinge:はい、そうです。私はそれがどのように動作するか説明するために答えを更新しました。 – ruakh

関連する問題