scala中curry函数的第n个参数的运算
发布时间:2020-12-16 10:00:36 所属栏目:安全 来源:网络整理
导读:我正在使用许多curried函数,采取类似的论点,但不完全.出于这个原因,我发现有一种方法可以执行第n个参数的转置,应用和组合,以及“最终”结果.例: val f :X=Y=W=Zdef compose1[A](w :A=Y) :X=A=W=Zdef transpose1 :X=W=Y=Zdef apply1(y :Y) :X=W=Z 对于n的固
我正在使用许多curried函数,采取类似的论点,但不完全.出于这个原因,我发现有一种方法可以执行第n个参数的转置,应用和组合,以及“最终”结果.例:
val f :X=>Y=>W=>Z def compose1[A](w :A=>Y) :X=>A=>W=>Z def transpose1 :X=>W=>Y=>Z def apply1(y :Y) :X=>W=>Z 对于n的固定值,可以很容易地完成它,如下所示: implicit class Apply2[X,Y,Z](private val f :X=>Y=>Z) extends AnyVal { def transpose :Y=>X=>Z = { y :Y => x :X => f(x)(y) } def provide(y :Y) :X=>Z ={ x :X => f(x)(y) } def compose[A](y :A=>Y) : X=>A=>Z = { x :X => a :A => f(x)(y(a)) } def apply[A,B]()(implicit ev :Z <:< (A=>B)) :Apply3[X,A,B] = new Apply3[X,B]((x :X) => (y :Y) => ev(f(x)(y))) } 但是,我当然不欢迎复制和发送此类22个版本的想法.对于类型类的最后一个参数,我也可以很容易地做到这一点, val f :A=>B=>C=>D=>E=>F val c = f()().compose( (x :X) => new C(x)) :A=>B=>X=>D=>E=>F val t = f()().transpose :A=>B=>D=>C=>E=>F val s = f()().set(new C()) :A=>B=>D=>E=>F 通过隐式转换为一些Apply,它提供了一个递归的apply()方法,返回一个嵌套的Apply实例. 当所有类型都是已知的时,转换为HList并返回的粗暴解决方案起作用,但是不确定的’依赖性是一把双刃剑. 解决方法
好吧,我的思绪仍然痒但我终于明白了!但是,我在一段时间内做了最困难的编程任务.如果有人有改进的建议(包括命名,符号和一般语法),我会全神贯注.
/** Represents a partially applied,curried function `F` which is of the form `... X => A`,* where X is the type of the first argument after (partial) application. * Provides methods for manipulating functions `F` around this argument. * @tparam F type of the manipulated function in a curried form (non-empty sequence of single argument lists) * @tparam C[G] result of mapping partial result `(X=>A)` of function `F` to `G`. * @tparam X type of the argument represented by this instance * @tparam A result type of function F partially applied up to and including argument X */ abstract class Curry[F,C[G],X,A](private[funny] val f :F) { prev => /** Result of partial application of this function F up to and including parameter `X`. */ type Applied = A /** Replace X=>A with G as the result type of F. */ type Composed[G] = C[G] /** A function which takes argument `W` instead of `X` at this position. */ type Mapped[W] = Composed[W=>A] /** Provide a fixed value for this argument,removing it from the argument list. * For example,the result of `Curry{a :Any => b :Byte => c :Char => s"$a$b$c" }().set(1.toByte)` * (after inlining) would be a function `{a :Any => c :Char => s"$a${1.toByte}$c" }`. */ def set(x :X) :Composed[A] = applied[A](_(x)) /** Change the type of this argument by mapping intended argument type `W` to `X` before applying `f`. * For example,given a function `f :F <:< D=>O=>X=>A` and `x :W=>X`,the result is `{d :D => o :O => w :W => f(d)(o)(x(w)) }`. */ def map[W](x :W=>X) :Composed[W=>A] = applied[W=>A]{ r :(X=>A) => (w :W) => r(x(w)) } /** Map the result of partial application of this function up to argument `X` (not including). * For example,if `F =:= K=>L=>X=>A`,the result is a function `{k :K => l :L => map(f(k)(l)) }`. * @param map function taking the result of applying F up until argument `X`. * @return resul */ def applied[G](map :((X => A) => G)) :Composed[G] /** If the result of this partial application is a function `A <:< Y=>Z`,swap the order of arguments * in function `F` from `=>X=>Y=>` to `=>Y=>X=>`. */ def transpose[Y,Z](implicit ev :A<:<(Y=>Z)) :Composed[Y=>X=>Z] = applied[Y=>X=>Z] { r :(X=>A) => y :Y => x :X => ev(r(x))(y) } /** Skip to the next argument,i.e return an instance operating on the result of applying this function to argument `X`. */ def apply[Y,Z]()(implicit ev :this.type<:<Curry[F,C,Y=>Z]) = new NextArg[F,Z](ev(this)) /** Skip to the next argument,i.e return an instance operating on the result of applying this function to argument `X`. * Same as `apply()`,but forces an implicit conversion from function types which `apply` wouldn't. */ def __[Y,Z](implicit ev :this.type<:<Curry[F,Z](ev(this)) } /** Operations on curried functions. */ object Curry { type Self[G] = G type Compose[C[G],X] = { type L[G] = C[X=>G] } /** Extension methods for modifying curried functions at their first argument (and a source for advancing to subsequent arguments. */ @inline def apply[A,B](f :A=>B) :Arg0[A,B] = new Arg0(f) /** Implicit conversion providing extension methods on curried function types. Same as `apply`,but doesn't pollute namespace as much. */ @inline implicit def ImplicitCurry[A,B] = new Arg0(f) /** Operations on the first argument of this function. */ class Arg0[X,Y](x :X=>Y) extends Curry[X=>Y,Self,Y](x) { def applied[G](map: (X=>Y) => G) :G = map(f) } class NextArg[F,A](val prev :Curry[F,Y=>A]) extends Curry[F,(C Compose X)#L,A](prev.f) { override def applied[G](map: (Y => A) => G): prev.Composed[X => G] = prev.applied[X=>G] { g :(X=>Y=>A) => x :X => map(g(x)) } } } def f :Byte=>Short=>Int=>Long=>String = ??? import Curry.ImplicitCurry f.set(1.toByte) :(Short=>Int=>Long=>String) f.map((_:String).toByte) :(String=>Short=>Int=>Long=>String) f.__.set(1.toShort) :(Byte=>Int=>Long=>String) Curry(f)().map((_:String).toShort) : (Byte=>String=>Int=>Long=>String) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |