【问题标题】:Scala - Make signature of function parameter f of higher order function g dependent on varars of gScala - 使高阶函数 g 的函数参数 f 的签名依赖于 g 的 varars
【发布时间】:2014-05-22 18:04:56
【问题描述】:

我正在尝试定义一个高阶函数f,它在Scala 中接受可变数量的args 类型Wrapper[T]* 和函数参数g。

函数f 应该解封装传入args 的每个对象,然后使用解封装的参数调用g。因此,g 必须接受与args 包含的T 类型参数数量完全相同的参数。

我能做到的最接近的事情是将Seq[T] 传递给g 并在g 内部使用模式匹配。像下面这样:

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

f 定义如下:

def f[V](args: Wrapper[T]*)
        (g: (Seq[T]) => (V)) : V = {
  val params = args.map(x => x.unwrap())
  g(params)
}
  1. 没有模式怎么可能完成这样的事情 匹配?
  2. g的签名可以省略类型 通过使用类型推断,但前提是参数的数量是 固定的。在这种情况下如何做到这一点?
  3. 可以通过 不同类型的参数转换为可变参数,如果类型通配符是 使用args: Wrapper[_]*。此外,铸造结果 x.unwrap 到 AnyRef 并在 g 中使用模式匹配是 必要的。然而,这完全打破了类型推断和类型 安全。有没有更好的方法在可变参数中混合类型 在这种特殊情况下可能吗?

我也在考虑使用 scala makros 来完成这些任务。

【问题讨论】:

  • 仅供参考 List(T) params = args.map(x => x.unwrap) 不是有效的 scala 代码
  • 已修复。感谢您阅读。
  • 元组 -> 简单列出,列出 -> 元组不容易。也许Shapless' HList 可能会满足您的需求。

标签: scala pattern-matching type-inference variadic-functions higher-order-functions


【解决方案1】:

我没听错吗?我用一些已知类型替换了你的Wrapper,但这似乎不是必需的。

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

所以以后你可以这样做:

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

好的,我已经创建了自己的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)

关于您对类型安全和转换的担忧:如您所见,上面的代码中没有任何显式转换,并且由于您要与显式定义的类型进行模式匹配,您可能不必担心这些things - 如果某些未定义来源的项目将显示在您的输入中,scala.MatchError 将被抛出。

【讨论】:

  • 感谢您的回复,您说的对。如果我理解正确,这提供了对 3 的答案(我可以混合类型,并且在使用模式匹配时不必担心类型安全)。对 1 和 2 也有任何想法吗?
猜你喜欢
  • 1970-01-01
  • 2023-03-18
  • 2021-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多