2011-05-12 61 views
4

假設我有以下類Foo,即使用幾倍特技支持任何元數的一個函數:Scala的通用類支撐功能

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 
} 

有什麼辦法來定義我的基類,從而可以做到這一點?

回答

4

如果你能得到滿意的定義執行的功能,而不是方法,那麼這個工程:

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 
} 

否則,我想你會需要更多機械,以支持不同的arities實現方法簽名:

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 
}