2016-08-12 8 views
0

.map()では以下のステートメントは有効ですが、.flatMap()では有効ではないのはなぜですか?スカラ:タプル付きflatMap

val tupled = input.map(x => (x*2, x*3)) 

//Compilation error: cannot resolve reference flatMap with such signature 
val tupled = input.flatMap(x => (x*2, x*3)) 

この文は、しかし、問題ありません:

val tupled = input.flatMap(x => List(x*2, x*3)) 
+0

「入力」とは何ですか? 'map'と' flatMap'メソッドのシグネチャを確認してください。そのパラメータが異なるため、コードにコンパイルエラーが発生します。 –

+0

'flatMap'は構造を平坦化するために使用されるためです。 'map [M]]を' M [A]]にすると 'flatMap'で' M [A] 'を得ます。 –

+0

ネストされた 'M'はときどき' N'と異なることがあります。例えば 'List [Option [String]]' => 'List [String]' –

答えて

3

flatMapIntからList[A]に関数を取るのに対し、タイプList[Int]の場合、mapは、IntからAする機能を取るinputを仮定します。

ユースケースによっては、どちらか一方を選択できますが、間違いなく互換性があります。例えば

、あなたは単にあなたが通常mapを使用したいListの要素を変換している場合:

List(1, 2, 3).map(x => x * 2) // List(2, 4, 6) 

いますが、Listの構造を変更したいと - 例えば - それぞれの「爆発」そして、それらを平坦化する別のリストに要素、flatMapはあなたの友達です:

あなたがしなければならなかったでしょう mapを使用して
List(1, 2, 3).flatMap(x => List.fill(x)(x)) // List(1, 2, 2, 3, 3, 3) 

代わりに10。

+1

@NathanielFordうん、そうだよ。更新されました –

1

これがどのように機能しているかを理解するには、送信する関数を明示的にmapflatMapに解凍し、その署名を調べると便利です。私はここに書き直しました。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関数は単一要素に対してどのように動作するかを知ることは期待されません。

関連する問題