9

私は、私が望むような振る舞いをすることができないコードを持っています。私は(このためにストリップダウン)、次のように定義されたクラスを持っている:複数のパラメータクロージャ引数型が推測されない

class Behaviour[T](private val rule: Time => T) { 
    def map1[U, V](behaviour: Behaviour[U], func: (T, U) => V): Behaviour[V] = { 
    new Behaviour(time => func(this.at(time), behaviour.at(time))) 
    } 
} 

私は些細なことだろうと思ったものにしようとした、このクラスで遊ん:最後のために

val beh = Behaviour(time => 5) 
val beh2 = Behaviour(time => 5) 
beh.map1(beh2, (a, b) => a + b) 

私はもちろん閉鎖パラメータの型を指定することができます

<console>:13: error: missing parameter type 
      beh.map1(beh2, (a, b) => a + b) 
          ^

、それが正常に動作しますが、なぜここ推論作業を入力していない:行は、私は次のエラーを受け取りますか?もちろん、関数のジェネリック型を指定することもできます(両方のソリューションについては以下を参照してください)。

スカラはタイプを推測するために「スキャン」を実行し、beh2と表示され、関数に渡され、ここでがIntと仮定したと考えました。入力パラメータのタイプ(クロージャーまたはジェネリックス)を指定せずにこれを解決できる方法はありますか?

編集:私は持っている2つの修正の例:この問題を解決する方法の

beh.map1[Int, Int](beh2, (a, b) => a + b) 
beh.map1(beh2, (a, b : Int) => a + b) 

答えて

19

ここでの説明については、this scala-debate threadを参照してください。 Scalaの型推論はパラメータリストで行われ、パラメータではではないという問題があります。

Josh Suerethがこのスレッドでメモしているように、現在のアプローチには十分な理由があります。 Scalaにパラメータごとの型推論があった場合、コンパイラは同じパラメータリストの型間で上限を推測できませんでした。次のことを考えてみましょう:

trait X 
class Y extends X 
class Z extends X 

val y = new Y 
val z = new Z 

def f[A](a: A, b: A): (A, A) = (a, b) 
def g[A](a: A)(b: A): (A, A) = (a, b) 

f(y, z)は、我々が期待どおりに動作しますが、時間によって、コンパイラは、それがすでにAの型としてYを選んだ第​​二引数リストになるので、g(y)(z)は、型の不一致を示します。

4

一つは、複数の引数リストを定義することです。

def map1[U, V](behaviour: Behaviour[U])(func: (T, U) => V): Behaviour[V] = ... 

、あなたはこのようにそれを使用することができます:だからあなたのmap1方法は次のように定義されるだろう

beh.map1(beh2)((a, b) => a + b) 
beh.map1(beh2)(_ + _) 

私は型推論は、あなたのケースでは動作しない理由を完全にわからないんだけど、IそれはU型パラメータの使用法と関係があると考えています。最初の引数と2番目の引数に対して2回使用しています。コンパイラがそれを理解するのはあまりにも複雑すぎるでしょう。 2つの引数リストの場合は、最初の引数リストのコンパイル中にUが推論され、2番目の引数リストはすでに推論された型を使用します。

+0

ありがとうございました。翌日に何が起こっているのか説明できない場合は、私はその答えを受け入れます。 – seadowg

関連する問題