gpt4 book ai didi

scala - 有没有一种通用的方法来反转柯里化(Currying)函数的参数顺序?

转载 作者:行者123 更新时间:2023-12-04 23:55:26 27 4
gpt4 key购买 nike

我想知道您是否可以编写一个通用函数,该函数接受一个柯里化(Currying)函数,然后反转参数,如下所示:

def foo(a: String)(b: Boolean)(c: Int): String
val bar = invert(foo _)
foo("baz")(false)(12) must be equalTo(bar(12)(false)("baz"))

只要您为要解决的特定情况添加隐式逆变器,以下内容就可以工作。但我对更一般的情况更感兴趣——即处理任意数量的柯里化(Currying)参数的情况。
trait Inverter[V, W] {
def invert(v: V): W
}

implicit def function2Inverter[X, Y, Z] =
new Inverter[(X, Y) => Z, (Y, X) => Z] {
def invert(v: (X, Y) => Z) = {
def inverted(y: Y, x: X) = v(x, y)
inverted _
}
}

implicit def curried2Inverter[X, Y, Z] =
new Inverter[X => Y => Z, Y => X => Z] {
def invert(v: (X) => (Y) => Z) = {
def inverted(y: Y)(x: X) = v(x)(y)
inverted _
}
}

def invert[V, W](v: V)(implicit inverter: Inverter[V, W]): W =
inverter.invert(v)

哦,我也希望有一个适用于 Scala 2.9 的解决方案。

最佳答案

TL;DR:使用 this gist .相同的解释如下:

首先,定义一个类型类(和案例)以部分应用带有最后一个参数的函数:

trait PopLast[A, Last, Rem] {
def pop(f: A, v: Last): Rem
}

trait LowPrioPopLast {
implicit def popEnd[A,B] = new PopLast[A => B, A, B] {
def pop(f: A => B, v: A) = f(v)
}
}

object PopLast extends LowPrioPopLast {
implicit def popOne[A, B, C, Last, IRem](
implicit iPop: PopLast[B => C, Last, IRem]) =
new PopLast[A => B => C, Last, A => IRem] {
def pop(f: A => B => C, v: Last) = { a: A => iPop.pop(f(a), v) }
}
}

然后,创建逆变器类型类:递归地对最后一个参数进行部分应用并反转结果。
trait Inverter[A] {
type Out
def invert(f: A): Out
}

trait LowPrioInverter {
implicit def invertEnd[A,B] = new Inverter[A => B] {
type Out = A => B
def invert(f: A => B) = f
}
}

object Inverter extends LowPrioInverter {
implicit def invertStep[A, Last, Rem](implicit pop: PopLast[A, Last, Rem],
inv: Inverter[Rem]) = new Inverter[A] {
type Out = Last => inv.Out
def invert(f: A) = { a: Last => inv.invert(pop.pop(f, a)) }
}
}

最后,封装成一个函数:
def invert[A](f: A)(implicit inv: Inverter[A]) = inv.invert(f)

我们开始了:
def foo(a: String)(b: Boolean)(c: Int): String = "bar"
val bar = invert(foo _)
// bar: Int => Boolean => String => String

bar(1)(true)("foo")

关于scala - 有没有一种通用的方法来反转柯里化(Currying)函数的参数顺序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17068464/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com