Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Scala中,泛型类型参数可以与*函数*定义一起使用吗?_Scala_Generics - Fatal编程技术网

在Scala中,泛型类型参数可以与*函数*定义一起使用吗?

在Scala中,泛型类型参数可以与*函数*定义一起使用吗?,scala,generics,Scala,Generics,是否有语法允许对函数文本使用泛型类型参数?我知道我可以用一种方法来包装它,比如: def createLongStringFunction[T](): (T) => Boolean = { (obj: T) => obj.toString.length > 7 } 但是我最终需要为每个类型T调用该方法并获得一个新函数。我查看了语言参考,虽然我看到编译器将函数文本语法转换为本身具有通用输入类型的Functionn对象的实例,但看起来编译器魔术在创建时实现了这些参数。实际上,

是否有语法允许对函数文本使用泛型类型参数?我知道我可以用一种方法来包装它,比如:

def createLongStringFunction[T](): (T) => Boolean = {
  (obj: T) => obj.toString.length > 7
}
但是我最终需要为每个类型T调用该方法并获得一个新函数。我查看了语言参考,虽然我看到编译器将函数文本语法转换为本身具有通用输入类型的Functionn对象的实例,但看起来编译器魔术在创建时实现了这些参数。实际上,我还没有找到任何语法允许我“使function的一个或多个类型参数处于未绑定状态”。我更喜欢的是以下内容:

// doesn't compile
val longStringFunction: [T](T) => Boolean = (obj: T) => obj.toString.length > 7
有这样的东西吗?或者,当被展开的方法具有泛型参数时,eta展开函数的显式类型是什么


这纯粹是一个做作而无用的例子。当然,我可以让函数在这里使用任意值。

不,类型参数只适用于方法,而不适用于函数对象。比如说,

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
def[T](x:T)=x/>f[T](x:T)T
val g=f/>g:Nothing=>Nothing=
//g(2)//错误
val h:Int=>Int=f u/>h:Int=>Int=
h(2)/>res0:Int=2

方法
f
无法转换为多态函数对象
g
。如您所见,
g
的推断类型实际上是
Function1[Nothing,Nothing]
,这是无用的。但是,通过类型提示,我们可以构造
h:Function1[Int,Int]
,该函数按照
Int
参数的预期工作。

因为下面定义的
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
scala>val funObj:Any=>Boolean=\uu.toString.size>7
funObj:Any=>Boolean=
scala>def typedFunction[T]:T=>Boolean=funObj
typedFunction:[T]=>T=>Boolean
scala>val f1=typedFunction[字符串]
f1:String=>Boolean=
scala>val f2=typedFunction[Int]
f2:Int=>Boolean=
scala>f1等式f2
res0:Boolean=true

这是因为
trait function 1[-T1,+R]
类型
T1
的逆变型,正如您所说,在您的示例中,您需要的只是
toString
方法,因此
任何
都是通常的解决方案。然而,在诸如对元组中的每个元素应用类型构造函数(如
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))

在scala中,函数值是参数单态的(而方法是多态的)

Shapeless库引入了多态函数值,这些值可以映射到HLists和许多其他功能上

请考虑以下参考文献:


啊,没错。这实际上只是将其转换为更受约束的类型。事实上,我们可以完全放弃该方法,只分配函数,例如
valf1:String=>Boolean=funObj
谢谢,我担心可能是这样。不过,以这种方式扩展方法确实为更复杂的情况打开了大门。虽然我找不到没有中间方法的方法,但赋值的类型提示却可以达到令人惊讶的程度,例如:
def-doStuff[t,U](moreStuff:t=>U)(obj:t)=moreStuff(obj)val-timeandhalf=doStuff[Int,Double](*1.5)
,它与显式对应的
def-doStuff[t,U]有相当大的差异(moreStuff:T=>U)(obj:T):U=moreStuff(obj)val time和half:Int=>Double=(num:Int)=>doStuff[Int,Double](num=>num*1.5)(num)
类型参数不适用于函数对象的原因是什么?@PaulCarey请查看此链接,虽然此链接可能会回答问题,但最好在此处包含答案的基本部分,并提供链接供参考。如果链接页面发生更改,则仅链接的答案可能无效。@Sasam该答案不包括t他是答案的关键部分!