加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 是否有一种通用的方法来反转curried函数的参数顺序?

发布时间:2020-12-16 18:04:16 所属栏目:安全 来源:网络整理
导读:我想知道你是否可以编写一个泛型函数,它接受一个curried函数,然后反转参数,如下所示: def foo(a: String)(b: Boolean)(c: Int): Stringval bar = invert(foo _)foo("baz")(false)(12) must be equalTo(bar(12)(false)("baz")) 只要您为要解决的特定情况添加
我想知道你是否可以编写一个泛型函数,它接受一个curried函数,然后反转参数,如下所示:

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

只要您为要解决的特定情况添加隐式逆变器,以下操作就可以正常工作.但我对更一般的情况更感兴趣 – 也就是说,处理任何数量的讨论论点的情况.

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,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,IRem](
    implicit iPop: PopLast[B => C,IRem]) = 
      new PopLast[A => B => C,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,Rem](implicit pop: PopLast[A,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")

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读