2014-07-17 101 views
1

让我们说,我们有以下斯卡拉:协变函数

trait Foo 

    class Bar extends Foo 

    def foobar(fn: Option[Set[_ <: Foo] => Unit]) {} 

    def main(args: Array[String]) { 
    foobar(Option(bar)) //doesnt compile 
    } 

    def bar(input: Set[Bar]) {} 

代码片断这行得编译,因为函数一个被定义为trait Function1 [-T1, +R] extends AnyRef。无论如何,我的问题是在Scala中编写一个函数,它需要一个T型或其子类型并执行一些操作?或者,正如我害怕它不可能

回答

3

可以在foobar移动为Set类型约束出来的类型参数的函数本身:

trait Foo { 

    class Bar extends Foo 

    def foobar[A <: Foo](fn: Option[Set[A] => Unit]) {} 

    def main(args: Array[String]) { 
     foobar(Option(bar _)) //compiles! 
    } 

    def bar(input: Set[Bar]) {} 

} 

Scala编译器将传递到foobar参数推断出类型A,同时仍然执行类型约束。此外,您需要部分应用bar以将其传入Option

1

如何

trait Foo 

class Bar extends Foo 

def bar(input: Set[_ <: Foo]) {} 

def foobar(fn: Option[Set[_ <: Foo] => Unit]) {} 

foobar(Some(bar(_))) // partially applied 

foobar(None) 

你现在可以做这样的事情在某些情况下完全适用foobar的()

val x = Set(new Bar()) 

foobar(Some(x => bar(x))) 

注意,它为x => bar(x),因为类型是函数对象的一部分,而不是函数的结果。

1

如果你想使用existentials而非杰西的答案,你可以有这样的:

def foobar(fn: Option[(Set[X] => Unit) forSome { type X <: Foo }]) {} 
foobar(Option(bar _))