kmizuの日記

プログラミングや形式言語に関係のあることを書いたり書かなかったり。

オーバーロードされたメソッドをeta-expansionする

eta-expansionとは、メソッドを関数に変換する処理です。 たとえば、

def add(x: Int, y: Int): Int = x + y
val addFunc = add _

で、add _によって、eta-expansionが行われ、メソッドaddが関数に変換されます。このeta-expansion、メソッドがオーバーロードされていると一見正しく行うことができないように見えます。

object O {
  def add(x: Double, y: Int): Double = x + y
  def add(x: Int, y: Double): Double = x + y
}
O.add _
<console>:13: error: ambiguous reference to overloaded definition,
both method add in object O of type (x: Int, y: Double)Double
and  method add in object O of type (x: Double, y: Int)Double
match expected type ?
       O.add _
         ^

これに対して、次のようにしてやればeta-expansionを行うことができます。

object O {
  def add(x: Double, y: Int): Double = x + y
  def add(x: Int, y: Double): Double = x + y
}
O.add _:((Double, Int) => Double)

要はどのような型の関数に変換するか明示してやればいいわけです。eta-expansionは変換先の型を意識せずにできるのがメリットなのでこうしなければいけない時点でメリットが半減シますが、一応回避策はある、ということで。