2

Scala2.10の理解のために構文の問題があります。

for(a <- List(Some(1,2)); b <- a) yield bに評価しますList(1,2)

では、なぜfor(a <- Some(List(1,2)); b <- a) yield b同じことを評価しないのですか?

タイプチェッカーは、2番目の式(b <-a)についてList[Int]Option[?]

4

2 に答える 2

7

私はこれをごく最近説明しました-うまくいけば誰かがリンクを見つけることができます。これは繰り返し発生する質問なので、閉鎖される可能性があります。

いずれにせよ、外部ジェネレーターが表現を制御します。それは各レベルで起こるので、私がこれを持っている場合:

for { 
  a <- A
  b <- B
  c <- C
} yield f(a, b, c)

次に、の表現f(a, b, c)はによって制御されC、その表現はによって制御されB、最終結果の表現はによって制御されAます。したがって、ほとんどの実用的な目的では、理解のための表現は最初のジェネレーターによって制御されます。

では、「表現」とはどういう意味ですか?ええと、理解のためのは、通常、単調な理解です(実際には、とのようなメソッドへの呼び出しのセットであるflatMapため、タイプチェックするものmapであれば何でもかまいません)。つまり、モナドM[A]と関数が与えられた場合A => M[B]、次のように変換できます。ここM[A]で、モナドは「表現」です。M[B]M

これは、ほとんどの場合、組み合わせて理解することは不可能であることを意味しOptionますList。すべてのコレクションには共通の親がGenTraversableOnceあるため、それらを組み合わせても問題はありません(ただし、内部のコレクションよりもはるかに複雑です)。

Optionただし、からへの暗黙の変換がありIterableます。その場合、Scalaが最初の例で見つけ、理解がによって「制御」されているためにb <- a通過できないことを知っていると、 Scalaはに変換され、すべてが機能します。OptionListOptionIterable

ただし、2番目のケースでは発生しません。で理解のためにを行うことはOption問題ないので、それをに変換する必要はありませんIterable。残念ながら、をに変換することはできず(そのようなList変換Optionの結果はどうなるでしょうか?)、エラーが発生します。

Scalaの型推論は前進するだけなので、Scalaは「バックトラック」しa <- Some(List(1, 2))て暗黙の変換を適用しません。以前に決定したことはそのままです。

関連する質問を見て、理解のためにどのように翻訳されるかを理解することを心からお勧めします。

于 2013-02-19T04:56:55.587 に答える
2

ダニエルはこれの複雑さを説明しました。しかし、詳細を追加したいと思います。なぜなら、この動作は非常に直感的ではなく、この混合の問題に何度か遭遇したからですOptionListご覧のとおり、一方向では機能しますが、他の方向では機能しないため、特に厄介です。

だから、理解のためのルールに従って、あなたは持っているでしょう

def test(a: Option[List[Int]]) = a.flatMap(_.map(identity))

で失敗する

<console>:7: error: type mismatch;
 found   : List[Int]
 required: Option[?]
           def test(a: Option[List[Int]]) = a.flatMap(_.map(identity))
                                                           ^

しかし、あなたはそれを機能させることができます:

def test(a: Option[List[Int]]) = (a: Iterable[List[Int]]).flatMap(_.map(identity))

test(Some(List(1,2)))  // List(1,2)

または戻ってfor

for(a <- Some(List(1,2)).toIterable; b <- a) yield b

forこの変換を単独で課す必要がありますか?正直なところわかりませんが、うまくいかないという驚きを共有します。

于 2013-02-19T08:59:01.113 に答える