对于记录,我发现在Scala中不会自动调整函数非常烦人。我正在尝试编写一个接受任何功能的工厂并返回一个curried版本:
def curry(fn:(_ => _)) = (fn _).curried
基本上我在这里定义的是一个函数curry
,它将fn
类型的函数_ => _
作为参数,并返回函数fn
的curried版本。显然这不起作用,因为Java。
这是我得到的错误:
error: _ must follow method; cannot follow fn.type
def curry(fn:(_ => _)) = (fn _).curried
那里的任何大师都可以帮我弄清楚为什么这不起作用?我并不意味着听起来很讽刺,我习惯于将所有类型作为函数处理的函数式语言。请帮助这个Scala新手。
(我用haskell标记了这个问题,因为我试图让Scala函数像Haskell函数一样运行:'(
更新
只是为了澄清,我需要一个curryN
函数,所以这个函数可以解释任何其他函数而不管它是什么。
旁注,有些人指出增加fn的参数可以解决问题。都能跟得上:
def curry2(fn:((_, _) => _)) = (fn _).curried
error: _ must follow method; cannot follow fn.type
def curry2(fn:((_, _) => _)) = (fn _).curried
答案 0 :(得分:7)
Scala不允许您对函数的arity进行抽象。因此,您需要使用类型类方法(在完成所有手动工作之后,它允许您抽象几乎所有内容)。
所以,特别是,你做了类似
的事情sealed trait FunctionCurrier[Unc, Cur] { def apply(fn: Unc): Cur }
final class Function2Currier[A, B, Z]
extends FunctionCurrier[(A, B) => Z, A => B => Z] {
def apply(fn: (A, B) => Z): (A => B => Z) = fn.curried
}
// Repeat for Function3 through Function21
implicit def makeCurrierForFunction2[A, B, Z]: Function2Currier[A, B, Z] =
new Function2Currier[A, B, Z]
// Again, repeat for Function3 through Function21
def curryAll[Unc, Cur](fn: Unc)(implicit cf: FunctionCurrier[Unc, Cur]): Cur =
cf(fn)
现在您可以这样使用它:
scala> def foo(a: Int, b: String) = a < b.length
foo: (a: Int, b: String)Boolean
scala> curryAll(foo _)
res0: Int => (String => Boolean) = <function1>
在Shapeless中可能已经有类似的东西了,但是在这种情况下你可以自己滚动,虽然有些乏味(和/或代码生成器)。
(注意:如果您想要&#34;咖喱&#34; A => Z
,您可以编写一个Function1Currier
,只返回未触及的功能。)
答案 1 :(得分:0)
这可以使用curried
函数方法完成。你需要将函数本身作为一个部分应用的函数来访问并得到它的curried形式,如下所示:
def fn(i: Int, j: Int) = i + j
val fnCurryable = (fn _).curried
val fnCurried = fnCurryable(1)
println(fnCurried(2))
//prints 3
由于scala的强大类型推断,相同的第二行可以用2-22个参数来计算任何函数。另外,请记住,您可以在声明中声明您的函数是可以理解的。这将与上面相同:
def fnCurryable(i: Int)(j: Int) = i + j
使用多个参数列表意味着此函数被称为fnCurryable(1)(2)
,并且永远不能被称为fnCurryable(1, 2)
。此转换基本上是.curried
的作用。
这基于以下描述的功能特征:
http://www.scala-lang.org/api/2.11.8/index.html#scala.package
答案 2 :(得分:0)
def toCurry[A](f: (A, A) => A): A => A => A = x => f(x, _)
val addTwoNum = (x: Int, y: Int) => x + y
val curriedAddTwoNum = toCurry(addTwoNum)
val part1Curry = curriedAddTwoNum(5)
println(part1Curry(2))
为获得更多便利,您只需在上述函数定义中添加其他参数即可。
的操作