これがどのように機能しているかを理解するには、送信する関数を明示的にmap
とflatMap
に解凍し、その署名を調べると便利です。私はここに書き直しました。f
は、Int
から(Int, Int)
タプルまでの関数マッピングであり、g
は、Int
からList[Int]
にマップする関数であることがわかります。
val f: (Int) => (Int, Int) = x => (x*2, x*3)
val g: (Int) => List[Int] = x => List(x*2, x*3)
List(1,2,3).map(f)
//res0: List[(Int, Int)] = List((2,3), (4,6), (6,9))
List(1,2,3).map(g)
//res1: List[List[Int]] = List(List(2, 3), List(4, 6), List(6, 9))
//List(1,2,3).flatMap(f) // This won't compile
List(1,2,3).flatMap(g)
//res2: List[Int] = List(2, 3, 4, 6, 6, 9)
なぜ、flatMap(f)
はコンパイルされませんか?さんはList
実装から引き出さこの場合には、flatMap
のための署名を見てみましょう:
final override def flatMap[B, That](f : scala.Function1[A, scala.collection.GenTraversableOnce[B]])(...)
これは、解凍には少し困難であり、私はそれの一部を省略さましたが、鍵がGenTraversableOnce
タイプです。 List
の場合、継承の連鎖に従えば、それはそれが構築された形質としてこれを持ちます。したがって、A
からList
(または特性がGenTraversableOnce
のオブジェクト)にマップする関数は有効な関数になります。特に、タプルにはこの特性がありません。
これは、タイピングが間違っている理由を説明するものであり、「そのようなシグネチャで参照を解決できません」というエラーがあると、明示的にあなたが提供しているタイプ。型はScalaで非常によく推測されるので、与えている型があなたが呼んでいるメソッドで期待される型であることを確認するのに適しています。
flatMap
は、関数プログラミングでは標準的な意味を持ちますが、おおまかに言えば、単一の要素を消費し、n個の要素を生成するマッピング関数ですが、最終的な結果はそれらすべてのリストの連結です。したがって、flatMap
に渡す関数は常にリストを生成することを期待し、flatMap
関数は単一要素に対してどのように動作するかを知ることは期待されません。
「入力」とは何ですか? 'map'と' flatMap'メソッドのシグネチャを確認してください。そのパラメータが異なるため、コードにコンパイルエラーが発生します。 –
'flatMap'は構造を平坦化するために使用されるためです。 'map [M]]を' M [A]]にすると 'flatMap'で' M [A] 'を得ます。 –
ネストされた 'M'はときどき' N'と異なることがあります。例えば 'List [Option [String]]' => 'List [String]' –