使用柯里化有什么好处?
首先,让我们澄清一些术语。人们使用“柯里化”来表示以下两个意思:
-
将两个参数的方法重新表述为一个参数的方法,该方法返回一个参数的方法 and
-
部分应用两个参数的方法来生成一个参数的方法.
显然,这两个任务密切相关,因此会造成混乱。在正式场合,人们应该将“柯里化”限制为指第一个定义,但在非正式场合,这两种用法都很常见。
所以,如果你有一个方法:
static int Add(int x, int y) { return x + y; }
你可以这样称呼它:
int result = Add(2, 3); // 5
你可以咖喱Add
method:
static Func<int, int> MakeAdder(int x) { return y => Add(x, y); }
and now:
Func<int, int> addTwo = MakeAdder(2);
int result = addTwo(3); // 5
在非正式场合,部分应用有时也称为“柯里化”,因为它显然是相关的:
Func<int, int> addTwo = y=>Add(2,y);
int result = addTwo(3);
您可以制作一台机器来为您执行此过程:
static Func<B, R> PartiallyApply<A, B, R>(Func<A, B, R> f, A a)
{
return (B b)=>f(a, b);
}
...
Func<int, int> addTwo = PartiallyApply<int, int, int>(Add, 2);
int result = addTwo(3); // 5
现在我们来回答你的问题:
使用柯里化有什么好处?
这两种技术的优点是它可以让您在处理方法时更加灵活。
例如,假设您正在编写路径查找算法的实现。您可能已经有一个辅助方法,可以为您提供两点之间的近似距离:
static double ApproximateDistance(Point p1, Point p2) { ... }
但是当你实际构建算法时,你经常想知道的是当前位置之间的距离是多少和一个固定的终点。什么算法needs is Func<Point, double>
-- 该位置到固定终点的距离是多少?你拥有的是Func<Point, Point, double>
。你将如何将你所拥有的转化为你所需要的?部分应用;您部分地将固定端点作为近似距离方法的第一个参数,并得到一个与路径查找算法需要消耗的函数相匹配的函数:
Func<Point, double> distanceFinder = PartiallyApply<Point, Point, double>(ApproximateDistance, givenEndPoint);
如果 ApproximateDistance 方法一开始就被柯里化了:
static Func<Point, double> MakeApproximateDistanceFinder(Point p1) { ... }
那么您就不需要自己进行部分应用;你只需打电话MakeApproximateDistanceFinder
有了固定的终点,你就完成了。
Func<Point, double> distanceFinder = MakeApproximateDistanceFinder(givenEndPoint);