是否有一种语法允许在函数文字上使用泛型类型参数?我知道我可以用以下方法包装它:
def createLongStringFunction[T](): (T) => Boolean = {
(obj: T) => obj.toString.length > 7
}
然后我最终需要为每个类型T调用该方法并获得一个新函数。我查看了语言参考,虽然我看到函数文字语法由编译器转换为 Functionn 对象的实例,该对象本身具有通用输入类型,但看起来编译器魔术实现了那些创建时的参数。我还没有找到任何允许我实际上“保留 Functionn 未绑定的一个或多个类型参数”的语法。我更喜欢的是:
// doesn't compile
val longStringFunction: [T](T) => Boolean = (obj: T) => obj.toString.length > 7
有这样的事吗?或者就此而言,当扩展方法具有通用参数时,eta扩展函数的显式类型是什么?
这是一个纯粹的人为和无用的例子。当然我可以在这里使用Any函数。
答案 0 :(得分:18)
不,类型参数仅适用于方法而不适用于函数对象。例如,
def f[T](x: T) = x //> f: [T](x: T)T
val g = f _ //> g: Nothing => Nothing = <function1>
// g(2) // error
val h: Int=>Int = f _ //> h : Int => Int = <function2>
h(2) //> res0: Int = 2
方法f
无法转换为多态函数对象g
。如您所见,g
的推断类型实际上是Function1[Nothing, Nothing]
,这是无用的。但是,通过类型提示,我们可以构造h: Function1[Int,Int]
,它与Int
参数的预期一致。
答案 1 :(得分:7)
正如您所说,在您的示例中,您要求的只是toString
方法,因此Any
是常用解决方案。但是,需要能够在诸如将List
之类的类型构造函数应用于元组中的每个元素的情况下使用更高级别的类型。
正如其他答案所提到的那样,没有直接的支持,但有一种相对不错的编码方式:
trait ~>[A[_],B[_]] {
def apply[X](a : A[X]) : B[X]
}
type Id[A] = A //necessary hack
object newList extends (Id ~> List) {
def apply[X](a : Id[X]) = List(a)
}
def tupleize[A,B, F[_]](f : Id ~> F, a : A, b : B) = (f(a), f(b))
tupleize(newList, 1, "Hello") // (List(1), List(Hello))
答案 2 :(得分:1)
由于longStringFunction
定义为值,因此必须包含给定类型。
val longStringFunction: (T) => Boolean = (obj: T) => obj.toString.length > 7
但是,您可以使用方法重用函数对象:
scala> val funObj: Any => Boolean = _.toString.size > 7
funObj: Any => Boolean = <function1>
scala> def typedFunction[T]: T => Boolean = funObj
typedFunction: [T]=> T => Boolean
scala> val f1 = typedFunction[String]
f1: String => Boolean = <function1>
scala> val f2 = typedFunction[Int]
f2: Int => Boolean = <function1>
scala> f1 eq f2
res0: Boolean = true
这是有效的,因为trait Function1[-T1, +R]
是类型为T1
的逆变。
答案 3 :(得分:1)
在scala中,函数值是参数化单形的(而方法是多态的)
无形库引入了多态函数值,可以映射到HLists和更多其他特性。
请考虑以下参考: http://www.chuusai.com/2012/04/27/shapeless-polymorphic-function-values-1/ http://www.chuusai.com/2012/05/10/shapeless-polymorphic-function-values-2/