我了解咖喱函数在实际中是如何工作的。
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import ode
vx = lambda x,y: -1 - x**2 + y
vy = lambda x,y: 1 + x - y**2
y0, x0 = 0.5, 0.6
def f(x, y):
return vy(x,y)/vx(x,y)
r = ode(f).set_integrator('vode', method='adams')
r.set_initial_value(y0, x0)
xf = 0.32
dx =-0.01
x, y = [x0,], [y0,]
while r.successful() and r.t < xf:
x.append(r.t+dx)
y.append(r.y[0])
#plot it
plt.figure()
plt.plot(x, y)
plt.axis('equal')
plt.show()
其中def plainSum(a: Int)(b: Int) = a + b
val plusOne = plainSum(1) _
是类型plusOne
的咖喱函数,可以应用于(Int) => Int
:
Int
独立地,当由Chiusano和Bjarnason读本书(第2章)《 Scala中的函数式编程》 时,它证明了将两个自变量的函数plusOne(10)
res0: Int = 11
引入函数的实现一个参数的形式可以通过以下方式编写:
f
我可以理解上面的实现,但是很难将签名与def curry[A, B, C](f: (A, B) => C): A => (B => C) =
a: A => b: B => f(a, b)
和plainSum
示例相关联。
plusOne
中的1
似乎对应于类型参数plainSum(1) _
,而函数值A
似乎对应于函数签名plusOne
Scala编译器在看到语句B => C
时如何应用上面的curry
签名?
答案 0 :(得分:2)
您正在将部分应用函数与currying混为一谈。在Scala中,它们存在一些差异:
plusOne
示例自然可以通过多参数列表来立即使用,该列表多接一个参数,并返回最后一个参数。
Your mistake is that you are trying to use currying twice when this notation()() already gives you currying.
同时,您可以通过向plainSum
函数添加curry
签名来达到相同的效果,
def curry[A, B, C](f: (A, B) => C): A => (B => C) =
(a: A) => (b: B) => f(a, b)
def plainSum(a: Int, b: Int) = a + b
val curriedSum = curry(plainSum)
val add2 = curriedSum(2)
add2(3)
不应将(部分应用程序和currying)两者与另一个称为部分函数的概念相混淆。
注意:红皮书fpinscala试图像在Scala库中那样在没有语法糖的情况下创建这些抽象。