我的一位同事给我发了一个问题如下:
实现执行currying的HOF(高阶函数) 你的功能签名如下:
def curry[A,B,C](f:(A,B) => C) : A => B => C
同样,实现一个执行uncurrying的函数,如下所示:
def uncurry[A,B,C](f:A => B => C): (A,B) => C
我理解currying的方式是,如果你有一个带有多个参数的函数,你可以重复将函数应用于每个参数,直到得到结果。
因此f:(A,B) => C
的某些内容变为A => f(A,_) => f(B)
????
并且不应该将此应用程序合并到一个函数中,如下所示:
f:A=>B=>C
将是f(A,B)
?
也许我只是对这里的语法感到困惑,但是如果有人能指出我在这里缺少的东西会很棒。
由于
答案 0 :(得分:12)
希望这个带有大量注释的完整工作示例很容易理解。如果您有任何疑问,请回复。
您可以通过将其放入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。”
答案 1 :(得分:8)
我不确定我真的理解你的问题 - 你想知道什么,除了实际的实施?如上所述,它应该是微不足道的:
def curry[A,B,C](f:(A,B) => C): A => B => C =
a => b => f(a,b)
a => b => f(a,b)
的含义是“一个参数a
的函数,其返回值为b => f(a,b)
,这又是一个参数b
,其返回值是您执行的f(a,b)
(其类型为C
)“
a => b => f(a, b)
如果有帮助可以写得更详细一点吗?
{ (a: A) => { // a function of *one* argument, `a`
(b: B) => { // a function of *one* argument, `b`
f(a, b) // whose return value is what you get of you execute `f(a,b)` (whose type is `C`)
}
}
}
和
def uncurry[A,B,C](f:A => B => C): (A,B) => C =
(a, b) => f(a)(b)
(a, b) => f(a)(b)
表示“两个参数(a, b)
的函数,其返回值是您第一次将a
应用于HoF时获得的值{ {1}},返回一个函数,该函数反过来使用f
来返回b
“。
这有帮助吗?