可以在Scala中编写类似于C++模板的泛型返回类型吗?

whe*_*ies 5 scala scala-2.8

在C++中,我可以执行以下操作:

template<typename T, typename V>
struct{
    void operator()(T _1, V _2){
        _2.foo( _1 );
    }
};
Run Code Online (Sandbox Code Playgroud)

这让我随意决定使用任何有一些名为"foo"的方法的对象,它采用某种类型"T",而不事先指定"foo"函数的参数类型和所述函数的返回类型.

当我看到Scala时,看到像Function1这样的特征,并且正在使用像.这样的函数定义

def foo[T<:{def foo():Unit}]( arg:T ) = //something
def bar( x:{def foo():Unit} ) = //something
def baz[T,V<:Function1[T,_]]( x:T, y:V ) = y( x )
Run Code Online (Sandbox Code Playgroud)

我看着自己,想想为什么我不能做同样的事情?为什么"baz"会返回Any?它不能在编译时推断出实际的返回类型吗?如果我甚至不使用它,为什么我必须声明返回类型"foo"?

我希望能够做到

def biff[T,V:{def foo( x:T ):Unit}] = //something
Run Code Online (Sandbox Code Playgroud)

要么

def boff[T<:{def foo( x:Double ):_}]( y:T ) = y.foo _
Run Code Online (Sandbox Code Playgroud)

你能做到这一点,我只是错过了一些东西吗?如果没有,为什么不呢?

Aar*_*rup 11

更新:

实际上,你可以做得更好,类型推断器帮助你:

def boff[T,R](y: T)(implicit e: T <:< {def foo(x: Double): R}) = e(y).foo _
Run Code Online (Sandbox Code Playgroud)

因为baz,相同的技术将改进类型推断:

def baz[T,R,V]( x:T, y:V )(implicit e: V <:< (T => R)) = e(y).apply( x )

scala> baz(1, (i: Int) => i+1) 
res0: Int = 2
Run Code Online (Sandbox Code Playgroud)

你可以通过currying做得更好:

def baz[T,R](x: T)(f: T => R) = f(x)
Run Code Online (Sandbox Code Playgroud)

第一解决方案

类型推断器不会T为您提供类型,但您可以这样做:

class Boff[T] {
   def apply[R](y: T)(implicit e: T <:< {def foo(x: Double): R}) = e(y).foo _
}
object boff { 
   def apply[T] = new Boff[T]
}
Run Code Online (Sandbox Code Playgroud)


Dan*_*ral 6

Scala和C++之间的根本区别在于Scala中的每个类都被编译一次,然后可以原样用于依赖它的任何东西,而C++中的模板化类必须为每个新依赖项编译.

因此,事实上,C++模板生成N个编译类,而Scala只生成一个.

它不能在编译时推断出实际的返回类型吗?

因为必须在编译类时决定,这可能与编译它的时间不同.