Scalaで何故か型が推論できないパターン

はじめに

ProjectEulerやってたら何故か型推論できなかったパターンを見つけたのでメモ。詳しい人理由教えて下さい…。

簡略化したコード

val xss: IndexedSeq[Array[Int]] = hoge()
xss.reverse.reduce { case (xs, ys) => // reduce以下の関数でThe argument types of an anonymous function must be fully known. (SLS 8.5)
  ys.zipWithIndex.map { case (y, i) =>
    math.max(xs(i), xs(i + 1)) + y
  }
}

回避する方法

とりあえず関数の型が分からんのなら関数定義して型明らかにすれば良いんだろうと、こんな感じに通した

val xss: Seq[Array[Int]] = hoge()
def f(xs: Array[Int], ys: Array[Int]): Array[Int] = {
  ys.zipWithIndex.map { case (y, i) =>
    math.max(xs(i), xs(i + 1)) + y
  }
}
xss.reverse.reduce(f)

一番のキモは関数の返り値が分からんぽくって、引数のみ補完した場合はうまくいかなかった。

勘違いだった

下のコメントにあるように、caseを外すだけで良かった。reduceのときはcase意味無いですね…。

xss.reverse.reduce { (xs, ys) =>
  ys.zipWithIndex.map { case (y, i) =>
    math.max(xs(i), xs(i + 1)) + y
  }
}

所感

tupleのmapとかでcase必要なのに、reduceのときは要らないとか、(特にHaskell経験者にありがちな)tupleを引数に取る関数と2引数の関数の混同すると駄目ですね。

あと、下のコメントにあるように、推論できない理由は色々なトレードオフの結果のようですね。詳しくはコメントで