我认为这可以通过无形库来实现。
我正在使用无形将匿名类转换为闭包。这需要使用hlisted
特征中的FnHListerAux
。
我想做的就是摆脱传入的虚函数,并返回一个围绕此函数的闭包,该闭包具有与F
相同的类型签名。如果没有异步执行的匿名类,这将很容易。有办法解决这个问题吗?
def async[F, A <: HList, R](
shell: Shell,
success: F,
failure: FunctionTypes.Failure,
dummy: F)(implicit h: FnHListerAux[F, A => R],
u: FnUnHListerAux[A => R, F]): F =
{ (args: A) =>
require(shell != null, "Shell cannot be null")
require(shell.getDisplay() != null, "The shell must have a display")
val display = shell.getDisplay()
display.asyncExec(new Runnable() {
def run(): Unit = {
try {
success.hlisted(args)
} catch {
case e: Throwable =>
failure(e)
}
}
})
dummy.hlisted(args)
}.unhlisted
答案 0 :(得分:3)
我将首先简化一下。假设我有一个函数f
。我事先并不知道它的优点,我不关心它的回归。我想用一些功能包装它并获得具有相同参数类型的函数。我也不关心这个结果函数返回什么,所以我也可以让它返回Unit
。
你可以编写一堆(好的,22个)函数,如下所示:
def wrap[A](f: A => Unit): A => Unit = ???
def wrap[A, B](f: (A, B) => Unit): (A, B) => Unit = ???
def wrap[A, B, C](f: (A, B, C) => Unit): (A, B, C) => Unit = ???
但你不想。
Shapeless绝对可以帮助您更一般地解决这个问题:
def wrap[F, A <: HList](f: F)(
implicit h: FnHListerAux[F, A => Unit], u: FnUnHListerAux[A => Unit, F]
): F = { (args: A) =>
println("Before!"); f.hlisted(args); println("After!")
}.unhlisted
这给了我们:
scala> def f(i: Int, s: String) { println(s * i) }
f: (i: Int, s: String)Unit
scala> val wf = wrap(f _)
wf: (Int, String) => Unit = <function2>
scala> wf(3, "ab")
Before!
ababab
After!
请注意,f
可能会返回Unit
以外的其他内容,但这仍然有效,因为Scala中的所有内容都是Unit
,而FunctionN
特征在返回时是协变的类型。
将此方法应用于您的代码,我们得到以下结果:
def async[F, A <: HList](
shell: Shell, success: F, failure: FunctionTypes.Failure
)(
implicit h: FnHListerAux[F, A => Unit], u: FnUnHListerAux[A => Unit, F]
): F = { (args: A) =>
require(shell != null, "Shell cannot be null")
require(shell.getDisplay() != null, "The shell must have a display")
val display = shell.getDisplay()
display.asyncExec(new Runnable() {
def run(): Unit = {
try {
success.hlisted(args)
} catch {
case e: Throwable =>
failure(e)
}
}
})
}.unhlisted
不需要dummy
。