2016-09-12 3 views
3

私はスカラーが初めてです。同じコードを2通り書きました。しかし、私は2つの方法の間で少し混乱しています。第2の方法では、引数fの型は自動的に導出されますが、型1ではスカラーコンパイラは同じことを行うことができません。私はちょうどこれの背後にある考えであるか理解したい。スカラでは、関数型を引数の別々のグループに渡して関数に渡す必要があります

タイプ1:コンパイルエラーに

def rightFold[A,B](xs:List[A],z:B,f:(A,B) => B): B = xs match { 

    case Nil => z 
    case Cons(x,xs) => f(x,rightFold(xs,z,f)) 
    } 

    def sum1(l:List[Int]) = rightFold(l,0.0,_ + _) 

タイプ2を提供します:罰金

def rightFold[A,B](xs:List[A],z:B)(f:(A,B) => B): B = xs match { 

    case Nil => z 
    case Cons(x,xs) => f(x,rightFold(xs,z)(f)) 
    } 

    def sum1(l:List[Int]) = rightFold(l,0.0)(_ + _) 
+0

Scalaで覚えておくべき大まかなガイドライン:型推論は完璧ではなく、カレーをかけるとうまくいく傾向があります。 –

答えて

3

ワークスこれは関数型に関するものではありません【選択問題である引数の別々のグループ(カリー)に渡す必要がありますScalaがまだ知らない型については+を使用しています。

関数をカレッジすると、コンパイラは最初の2つの引数の型をList[Int]Doubleとして既に推測できます。これにより、タイプがIntおよびDobuleであることが両側に分かっているので、+が解決されます。

なぜ、コンパイラは単一の引数リストで同じことをすることができないのですか?それは型情報が引数リスト内で利用できないことです。

3

_ + _を渡すのではなく、(a: Int, b: Double) => (a + b))を渡すとタイプ1が機能します。関数をカリングすると、アンダーライン構文を使用することができます。これは、スカラーコンパイラが、加算関数を試して渡すときにAとBの型が推測されているためです。

+0

'(_:Int)+(_:Double)'は最初のケースで動作し、 '(a、b)=> a + bは2番目に働く。 –

4

左からへの型推論は、引数リストによって行われます。 内の左側の引数から言い換えれば、型情報リストは、右引数でリスト利用可能ですが、引数の型と同じリスト独立を推論しています。

+0

@Mittag意味がある。 –

+0

まあ、明らかにそうでなければ、あなた(そしてこれによって噛まれている無数の人)はこの質問をしなかったでしょう;-)しかし、それはそうです。 Scalaの型推論*は、Haskellと比べて制限されています。 1つはScalaにサブタイプがあります。これは型推論を大規模に複雑にします。さらに、Scalaの保守担当者は、良い、*有用な*コンパイルエラーを損なうものについて非常に敏感です。 –

0

単一リストの場合、Aの推定タイプは、xsfのタイプによって異なります。しかし、引数の2つのリストでは、それはちょうどxsタイプに依存します。

関連する問題