Scala Function.tupled 和 Function.untupled 等价于变量 arity,或者用元组调用变量 arity 函数 [英] Scala Function.tupled and Function.untupled equivalent for variable arity, or, calling variable arity function with tuple

查看:32
本文介绍了Scala Function.tupled 和 Function.untupled 等价于变量 arity,或者用元组调用变量 arity 函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

昨晚我试图做一些关于接受和调用泛型函数的事情(即类型在调用站点上是已知的,但可能因调用站点而异,因此定义应该跨参数通用).

I was trying to do some stuff last night around accepting and calling a generic function (i.e. the type is known at the call site, but potentially varies across call sites, so the definition should be generic across arities).

例如,假设我有一个函数 f: (A, B, C, ...) =>Z.(实际上有很多这样的f,我事先不知道,所以我无法确定A, B, C, ..., Z的类型和数量代码>.)

For example, suppose I have a function f: (A, B, C, ...) => Z. (There are actually many such fs, which I do not know in advance, and so I cannot fix the types nor count of A, B, C, ..., Z.)

我正在努力实现以下目标.

I'm trying to achieve the following.

  1. 如何使用 (A, B, C, ...) 的实例一般地调用 f?如果事先知道 f 的签名,那么我可以做一些涉及 Function.tupled f 或等效的事情.

  1. How do I call f generically with an instance of (A, B, C, ...)? If the signature of f were known in advance, then I could do something involving Function.tupled f or equivalent.

我如何定义与 f 具有相同签名的另一个函数或方法(例如,某些objectapply 方法)代码>?也就是说,我如何定义 g(a, b, c, ...) 类型检查的 g 当且仅当 f(a, b, c, ...) 类型检查?为此,我正在研究 Shapeless 的 HList.据我目前所知,HList 至少解决了表示任意arity args 列表"的问题,而且,Shapeless 将解决与元组之间的转换问题.但是,我仍然不确定我是否理解这将如何适应泛型元数的函数(如果有的话).

How do I define another function or method (for example, some object's apply method) with the same signature as f? That is to say, how do I define a g for which g(a, b, c, ...) type checks if and only if f(a, b, c, ...) type checks? I was looking into Shapeless's HList for this. From what I can tell so far, HList at least solves the "representing an arbitrary arity args list" issue, and also, Shapeless would solve the conversion to and from tuple issue. However, I'm still not sure I understand how this would fit in with a function of generic arity, if at all.

如何定义另一个具有与 f 相关的类型签名的函数或方法?现在想到的最大例子是一些 h: (A, B, C, ...) =>SomeErrorThing[Z] \/Z.

How do I define another function or method with a related type signature to f? The biggest example that comes to mind now is some h: (A, B, C, ...) => SomeErrorThing[Z] \/ Z.

我记得前段时间看过一个关于 Shapeless 的会议演示.虽然演示者没有明确演示这些东西,但他们所做的演示(围绕抽象/泛化元组与 HLists 的各种技术)将使我相信使用相同的工具可以实现与上述类似的事情.

I remember watching a conference presentation on Shapeless some time ago. While the presenter did not explicitly demonstrate these things, what they did demonstrate (various techniques around abstracting/genericizing tuples vs HLists) would lead me to believe that similar things as the above are possible with the same tools.

提前致谢!

推荐答案

是的,Shapeless 绝对可以帮助您.例如,假设我们想要采用任意元数的函数并将其转换为相同元数的函数,但返回类型包含在 Option 中(我认为这将满足您问题的所有三点).

Yes, Shapeless can absolutely help you here. Suppose for example that we want to take a function of arbitrary arity and turn it into a function of the same arity but with the return type wrapped in Option (I think this will hit all three points of your question).

为了简单起见,我只想说Option 总是Some.这需要非常密集的四行:

To keep things simple I'll just say the Option is always Some. This takes a pretty dense four lines:

import shapeless._, ops.function._

def wrap[F, I <: HList, O](f: F)(implicit
  ftp: FnToProduct.Aux[F, I => O],
  ffp: FnFromProduct[I => Option[O]]
): ffp.Out = ffp(i => Some(ftp(f)(i)))

我们可以证明它有效:

scala> wrap((i: Int) => i + 1)
res0: Int => Option[Int] = <function1>

scala> wrap((i: Int, s: String, t: String) => (s * i) + t)
res1: (Int, String, String) => Option[String] = <function3>

scala> res1(3, "foo", "bar")
res2: Option[String] = Some(foofoofoobar)

注意适当的静态返回类型.现在看看如何它是如何工作的:

Note the appropriate static return types. Now for how it works:

FnToProduct 类型类提供证据,证明某些类型 F 是一个 FunctionN(对于某些 N)可以从某个HList 转换成函数到原来的输出类型.HList 函数(准确地说是一个 Function1)是实例的 Out 类型成员,或者 的第二个类型参数>FnToProduct.Aux 助手.

The FnToProduct type class provides evidence that some type F is a FunctionN (for some N) that can be converted into a function from some HList to the original output type. The HList function (a Function1, to be precise) is the Out type member of the instance, or the second type parameter of the FnToProduct.Aux helper.

FnFromProduct 正好相反——这证明某些 F 是从 HList 到某个输出的 Function1类型,可以转换为该输出类型的某种数量的函数.

FnFromProduct does the reverse—it's evidence that some F is a Function1 from an HList to some output type that can be converted into a function of some arity to that output type.

在我们的 wrap 方法中,我们使用 FnToProduct.Aux 来约束 FnToProduct 实例的 OutF 这样我们就可以在 FnFromProduct<的类型中引用 HList 参数列表和 O 结果类型/代码> 实例.实现就非常简单了——我们只是在适当的地方应用实例.

In our wrap method, we use FnToProduct.Aux to constrain the Out of the FnToProduct instance for F in such a way that we can refer to the HList parameter list and the O result type in the type of our FnFromProduct instance. The implementation is then pretty straightforward—we just apply the instances in the appropriate places.

这可能看起来很复杂,但是一旦您在 Scala 中使用这种泛型编程一段时间后,它就会变得或多或少直观,我们当然很乐意回答有关您使用的更具体问题案例.

This may all seem very complicated, but once you've worked with this kind of generic programming in Scala for a while it becomes more or less intuitive, and we'd of course be happy to answer more specific questions about your use case.

这篇关于Scala Function.tupled 和 Function.untupled 等价于变量 arity,或者用元组调用变量 arity 函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆