简体   繁体   English

Scala-使依赖于g的变量的高阶函数g的函数参数f签名

[英]Scala - Make signature of function parameter f of higher order function g dependent on varars of g

I am trying to define a higher order function f which accepts a variable number of parameters args of type Wrapper[T]* and a function parameter g in Scala. 我正在尝试定义一个高阶函数f ,该函数接受变量数量为Wrapper[T]*类型的参数args和Scala中的函数参数g

The function f should decapsulate each object passed in args and then call g with the decapsulated parameters. 函数f应该解封装在args传递的每个对象,然后使用解封装的参数调用g Therefore, g has to accept exactly the same number of parameters of type T as args contains. 因此, g必须接受与args包含的T类型参数数量完全相同的参数。

The closest thing I could achieve was to pass a Seq[T] to g and to use pattern matching inside of g . 我能实现的最接近的事情是将Seq[T]传递给g并在g内使用模式匹配。 Like the following: 如下所示:

f("This", "Is", "An", "Example")(x => x match {
  case Seq(a:String, b:String, c:String): //Do something.
})

With f defined like: f定义如下:

def f[V](args: Wrapper[T]*)
        (g: (Seq[T]) => (V)) : V = {
  val params = args.map(x => x.unwrap())
  g(params)
}
  1. How is it possible to accomplish a thing like this without pattern matching? 没有模式匹配,怎么可能完成这样的事情?
  2. It is possible to omit the types in the signature of g by using type inference, but only if the number of parameters is fixed. 可以通过使用类型推断来省略g签名中的类型,但前提是参数的数量是固定的。 How could this be done in this case? 在这种情况下怎么办?
  3. It is possible to pass different types of parameters into varargs, if a type wildcard is used args: Wrapper[_]* . 如果使用类型通配符args: Wrapper[_]* ,则可以将不同类型的参数传递给varargs args: Wrapper[_]* Additionally, casting the result of x.unwrap to AnyRef and using pattern matching in g is necessary. 另外, x.unwrapAnyRef的结果x.unwrapAnyRef并在g使用模式匹配。 This, however, completely breaks type inference and type safety. 但是,这完全破坏了类型推断和类型安全性。 Is there a better way to make mixing types in the varargs possible in this special case? 在这种特殊情况下,是否有更好的方法来使varargs中的混合类型成为可能?

I am also considering the use of scala makros to accomplish these tasks. 我也在考虑使用scala makros来完成这些任务。

Did I get you right? 我说对了吗? I replaced your Wrapper with some known type, but that doesn't seem to be essential. 我用某种已知的类型替换了您的Wrapper ,但这似乎不是必需的。

def f[T, V](args: T*)(g: PartialFunction[Seq[T], V]): V = g(args)

So later you can do this: 因此,稍后您可以执行以下操作:

f(1,2,3) { case Seq(a,b,c) => c } // Int = 3

Okay, I've made my own Wrapper to be totally clear: 好的,我已经明确了自己的Wrapper

case class Wrapper[T](val x:T) { 
  def unwrap = x 
}

def f[V](args: Wrapper[_]*)(g: PartialFunction[Seq[_], V]): V =
  g(args.map(_.unwrap))

f(Wrapper("1"), Wrapper(1), Wrapper(BigInt(1))) {
  case Seq(s: String, i: Int, b: BigInt) => (s, i, b)
} // res3: (String, Int, BigInt) = (1,1,1)

Regarding your concerns about type safety and conversions: as you can see, there aren't any explicit conversions in the code above, and since you are going to pattern-match with explicitly defined types, you may not to worry about these things - if some items of an undefined origin are going to show in your input, scala.MatchError will be thrown. 关于类型安全性和转换的担忧:如您所见,上面的代码中没有任何显式转换,并且由于您要与显式定义的类型进行模式匹配,因此您不必担心这些事情-如果输入scala.MatchError显示一些未定义来源的项目, scala.MatchError将被抛出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM