scala - 实现在 scala 中执行柯里化(Currying)的高阶函数

标签 scala currying higher-order-functions

我的一位同事向我发送了一个问题,如下:

Implement a HOF(higher order function) that performs currying, the signature of your function is as follows:

def curry[A,B,C](f:(A,B) => C) : A => B => C

Similarly, implement a function that performs uncurrying as follows:

def uncurry[A,B,C](f:A => B => C): (A,B) => C

我理解柯里化(Currying)的方式是,如果你有一个接受多个参数的函数,你可以重复将该函数应用于每个参数,直到得到结果。

因此,类似于 f:(A,B) => C 的内容会变成 A => f(A,_) => f(B) ????

非柯里化(Currying)就是将此应用程序合并为一个函数,如下所示:

f:A=>B=>C 会是 f(A,B)

也许我只是对这里的语法感到困惑,但如果有人能指出我在这里缺少的东西,那就太好了。

谢谢

最佳答案

希望这个包含大量注释的完整示例易于理解。有问题请回复。

您可以通过将其放入 Scala 解释器来执行此代码。

// Here's a trait encapsulating the definition your coworker sent.
trait Given {
  def curry[A,B,C](f:(A,B) => C) : A => B => C
  def uncurry[A,B,C](f:A => B => C): (A,B) => C
}

object Impl extends Given {
  // I'm going to implement uncurry first because it's the easier of the
  // two to understand.  The bit in curly braces after the equal sign is a
  // function literal which takes two arguments and applies the to (i.e.
  // uses it as the arguments for) a function which returns a function.
  // It then passes the second argument to the returned function.
  // Finally it returns the value of the second function.
  def uncurry[A,B,C](f:A => B => C): (A,B) => C = { (a: A, b: B) => f(a)(b) }

  // The bit in curly braces after the equal sign is a function literal
  // which takes one argument and returns a new function.  I.e., curry()
  // returns a function which when called returns another function
  def curry[A,B,C](f:(A,B) => C) : A => B => C = { (a: A) => { (b: B) => f(a,b) } }
}

def add(a: Int, b: Long): Double = a.toDouble + b
val spicyAdd = Impl.curry(add)
println(spicyAdd(1)(2L)) // prints "3.0"
val increment = spicyAdd(1) // increment holds a function which takes a long and adds 1 to it.
println(increment(1L)) // prints "2.0"
val unspicedAdd = Impl.uncurry(spicyAdd)
println(unspicedAdd(4, 5L)) // prints "9.0"

一个较少数值的例子怎么样?

def log(level: String, message: String) { 
  println("%s: %s".format(level, message)) 
} 
val spicyLog = Impl.curry(log) // spicyLog's type is String => Unit
val logDebug = spicyLog("debug") // This new function will always prefix the log
                                 // message with "debug".
val logWarn = spicyLog("warn") // This new function will always prefix the log 
                               // message with "warn".
logDebug("Hi, sc_ray!") // prints "debug: Hi, sc_ray!"
logWarn("Something is wrong.") // prints "warn: Something is wrong."

更新 您回答说“编译器如何计算诸如 a => b => f(a,b) 这样的表达式。”嗯,事实并非如此。至少在你同事的代码片段中定义事物的方式是无法编译的。不过,一般来说,如果您看到 A => B => C 形式的内容,则表示“一个采用 A 作为参数的函数;它返回一个采用 B 作为参数的函数”并返回 C。”

关于scala - 实现在 scala 中执行柯里化(Currying)的高阶函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13793756/

相关文章:

javascript - 使用高阶函数,如果另一个值为 true,则返回一个对象值 (JavaScript)

typescript - TypeScript 3 的通用 curry 函数

javascript - 绑定(bind)函数的意外行为

macros - 将 Clojure 宏用于 DSL

javascript - 未捕获的语法错误 : Invalid or unexpected token in javascript with scala

grails - 使用 Curry 定义 Grails 标签

javascript - react : Is it possible to call a higher-order component within a container component?

scala - 如何检查 Any 值是否为空?

scala - 我无法理解 Scala Spark 中的 'RDD.map{ case (A, B) => A } '

scala - Spark Filter/Predicate Pushdown 是否在 ORC 文件中没有按预期工作?