5

私は最近 Scala を学んでいますが、今日、理解できない問題に遭遇しました。

次のパラメトリック関数定義があるとします。

def filter[T](source: List[T], predicate: T=>Boolean): List[T] = {
    source match {
        case Nil => Nil
        case x::xs => if(predicate(x)) x::filter(xs, predicate)
                  else filter(xs, predicate)
    }
}

さて、次のように呼び出すと、これはうまく機能します。

filter(List(1,2,3,4,5,6), ( (n:Int) => n % 2 == 0))

しかし、type タグを削除すると、Scala は T の型が Int であると推測できないようです。

filter(List(1,2,3,4,5,6), ( n => n % 2 == 0))

したがって、この呼び出しでは明示的な型情報を提供する必要があります。

この呼び出しで Scala が T の型を推論できない理由を知っている人はいますか? リストは明らかに Int のリストですが、n の型も Int であると推論できない理由がわかりません。

4

2 に答える 2

8

Scala の型推論は、パラメーターごとではなくパラメーターリストごとに機能するため、2 番目の例の述語に到達するまでには解決Tされていません。Intただし、次の 2 つのパラメーター リストを使用して、必要なものを取得できます。

def filter[T](source: List[T])(predicate: T => Boolean): List[T] =
  source match {
    case Nil => Nil
    case x :: xs =>
      if (predicate(x))
        x :: filter(xs)(predicate)
      else
        filter(xs)(predicate)
  }

これで、次のように問題なく動作します。

scala> filter(List(1, 2, 3, 4, 5, 6))((n => n % 2 == 0))
res0: List[Int] = List(2, 4, 6)

追加の議論については、こちらの回答を参照してください。

于 2013-03-04T23:20:50.357 に答える
1

推論を機能させるには、述語を他のパラメーターのグループに入れる必要があります。

def filter[T](source: List[T])(predicate: T=>Boolean): List[T] = {
    source match {
        case Nil => Nil
        case x::xs => if(predicate(x)) x::filter(xs)(predicate)
                   else filter(xs)(predicate)
    }
}

filter(List(1,2,3,4,5,6))(_ % 2 == 0)

残念ながら、これは scala の制限です。

于 2013-03-04T23:22:15.540 に答える