在 GitHub 上编辑此页面

元组函数

元组化函数

对于最多 22 个参数的函数,可以通过重载来泛化对所有函数类型的某些操作。现在,由于函数和元组已泛化到 超过 22 个参数,重载不再是选项。类型类 TupleFunction 提供了一种方法,可以将任意元数的函数抽象化,将其转换为接收所有参数的单个元组的等效函数。

/** Type class relating a `FunctionN[..., R]` with an equivalent tupled function `Function1[TupleN[...], R]`
 *
 *  @tparam F a function type
 *  @tparam G a tupled function type (function of arity 1 receiving a tuple as argument)
 */
@implicitNotFound("${F} cannot be tupled as ${G}")
sealed trait TupledFunction[F, G] {
  def tupled(f: F): G
  def untupled(g: G): F
}

如果满足以下条件,编译器将合成 TupledFunction[F, G] 的实例:

  • F 是元数为 N 的函数类型
  • G 是一个函数,它接受一个大小为 N 的元组作为参数,其类型与 F 的参数类型相同。
  • F 的返回值类型与 G 的返回值类型相同。
  • FG 是相同类型的函数(两者都是 (...) => R 或两者都是 (...) ?=> R)。
  • 如果 FG 中只有一个被实例化,则另一个将被推断。

示例

TupledFunction 可用于将 Function1.tupled、... Function22.tupled 方法泛化到任意元数的函数。以下将 tupled 定义为 扩展方法 (完整示例)。

/** Creates a tupled version of this function: instead of N arguments,
 *  it accepts a single [[scala.Tuple]] with N elements as argument.
 *
 *  @tparam F the function type
 *  @tparam Args the tuple type with the same types as the function arguments of F
 *  @tparam R the return type of F
 */
extension [F, Args <: Tuple, R](f: F)
  def tupled(using tf: TupledFunction[F, Args => R]): Args => R = tf.tupled(f)

TupledFunction 可用于将 Function.untupled 泛化到任意元数的函数 (完整示例)

/** Creates an untupled version of this function: instead of a single argument of type [[scala.Tuple]] with N elements,
 *  it accepts N arguments.
 *
 *  This is a generalization of [[scala.Function.untupled]] that work on functions of any arity
 *
 *  @tparam F the function type
 *  @tparam Args the tuple type with the same types as the function arguments of F
 *  @tparam R the return type of F
 */
extension [F, Args <: Tuple, R](f: Args => R)
  def untupled(using tf: TupledFunction[F, Args => R]): F = tf.untupled(f)

TupledFunction 还可用于将 Tuple1.composeTuple1.andThen 方法泛化,以组合更大元数的函数以及返回元组的函数。

/** Composes two instances of TupledFunction into a new TupledFunction, with this function applied last.
 *
 *  @tparam F a function type
 *  @tparam G a function type
 *  @tparam FArgs the tuple type with the same types as the function arguments of F and return type of G
 *  @tparam GArgs the tuple type with the same types as the function arguments of G
 *  @tparam R the return type of F
 */
extension [F, G, FArgs <: Tuple, GArgs <: Tuple, R](f: F)
  def compose(g: G)(using tg: TupledFunction[G, GArgs => FArgs], tf: TupledFunction[F, FArgs => R]): GArgs => R = {
  (x: GArgs) => tf.tupled(f)(tg.tupled(g)(x))
}