Универсальный класс поддержки Scala для нескольких множеств - PullRequest
4 голосов
/ 13 мая 2011

Предположим, у меня есть следующий класс Foo, который поддерживает функцию любой арности, используя трюк с кортежем:

abstract class Foo[T, R] {
  def pull: T => R
}

Я могу определить подкласс со следующим синтаксисом:

implicit def function2Tofunction1[T1, T2, R](f: (T1, T2) => R): ((T1, T2)) => R = {
    f.tupled 
}

class Moo extends Foo[(Int, Int), Int] {
  def pullImpl(x: Int, y:Int):Int = x + y
  def pull = (pullImpl _) // implicit converts to tupled form
}

val m = new Moo()
m.pull(4, 5)

Это довольно неуклюже. Идеальный синтаксис был бы следующим:

class Moo extends Foo[(Int, Int), Int] {
  def pullImpl(x: Int, y:Int):Int = x + y
}

Есть ли способ определить мой базовый класс так, чтобы этого можно было достичь?

1 Ответ

4 голосов
/ 13 мая 2011

Если вы можете быть удовлетворены определением реализации как функции, а не метода, тогда это работает:

abstract class Foo[T, R] {
   type Fn = T => R
   val pull: Fn
}

class Moo extends Foo[(Int, Int), Int] {
   // The type has to be explicit here, or you get an error about
   // an incompatible type. Using a type alias saves typing out
   // the whole type again; i.e. ((Int, Int)) => Int
   lazy val pull: Fn = (x: Int, y: Int) => x + y
}

В противном случае, я думаю, вам понадобится больше машин для поддержки сигнатур методов реализации для разных арностей:

trait Foo[T, R] { 
   type Fn = T => R
   val pull: T => R
} 

trait FooImpl2[T1, T2, R] extends Foo[(T1, T2), R] {
   lazy val pull: Fn = (pullImpl _).tupled
   protected def pullImpl(x: T1, y: T2): R
}

// similarly for FooImpl3, FooImpl4, ...

class Moo extends FooImpl2[Int, Int, Int] {
   protected def pullImpl(x: Int, y: Int) = x + y
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...