C#中的LINQ与柯里 [英] C# Linq vs. Currying

查看:114
本文介绍了C#中的LINQ与柯里的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我玩函数式编程和它的各种概念一点点。所有这些东西是很有趣的。有好几次我都了解钻营什么优势它。



但我没有得到这个点。下面的源演示咖喱概念和LINQ解决方案的采用。其实,我不认为使用概念钻营任何advatages。



那么,什么是使用钻营的优势在哪里?



 静布尔IsPrime(int值)
{
INT最大=(值/ 2)+ 1;
的for(int i = 2; I<最大;我++)
{
如果((值%I)== 0)
{
返回FALSE;
}
}
返回真;
}

静态只读Func键<&IEnumerable的LT; INT>中的IEnumerable< INT>> GetPrimes =
HigherOrder.GetFilter&所述; INT方式>()咖喱()(IsPrime);

静态无效的主要(字串[] args)
{
INT []号= {1,2,3,4,5,6,7,8,9, 10,11,12,13,14,15};

Console.Write(素数:);
//咖喱
的foreach(在GetPrimes INT N(数字))
{
Console.Write({0},N);
}
Console.WriteLine();

// LINQ的
的foreach(在numbers.Where INT N(p值=> IsPrime(P)))
{
Console.Write({0 },N);
}

到Console.ReadLine();
}

下面是高阶过滤法:

 公共静态Func键< Func键< TSource,布尔>中的IEnumerable< TSource>中的IEnumerable< TSource>>用getFilter< TSource>()
{
回油过滤器< TSource取代;
}


解决方案

什么是使用钻营的优势在哪里?




首先,让我们澄清一些条款。人们用钻营来表示两重新制定的两个参数的方法为返回一个参数的方法的一个参数的方法的两个参数的方法,以产生的方法的部分应用程序一个参数的的。显然这两个任务是密切相关的,并且因此混乱。当正式地说,一个人应该限制钻营指的第一个定义,但非正式的讲话时,无论使用是常见的。



所以,如果你有一个方法:

 静态INT加入(INT X,int y)对{返回X + Y; } 

您可以调用它是这样的:

  INT结果=添加(2,3); // 5 

您可以咖喱添加方法:

 静态Func键< INT,INT> MakeAdder(INT X){返回Y =>加(X,Y); } 

和现在:

  Func键< INT,INT> addTwo = MakeAdder(2); 
INT结果= addTwo(3); // 5



部分应用程序有时也被称为非正式说话的时候,因为这显然与钻营:

  Func键< INT,INT> addTwo = Y =>添加(2,y)的; 
INT结果= addTwo(3);

您可以做一个机器,这是否为您办理:

 静态Func键< b,R> PartiallyApply< A,B,R>(Func键< A,B,R> F,A一)
{
回报(B B)=> F(A,B);
}
...
Func键< INT,INT> addTwo = PartiallyApply< INT,INT,INT>(添加,2);
INT结果= addTwo(3); // 5



所以,现在我们来到你的问题:




什么是使用柯里的优点




任一技术的优点在于它可以让你在处理方法更灵活。



例如,假设你正在编写算法找到的路径的实现。您可能已经有一个给你两个点之间的大概距离一个辅助方法:

 静态双ApproximateDistance(点P1,P2点){...} 

但是当你实际构建算法,你经常想知道是什么是在当前位置的和一个固定端点的之间的距离。该算法什么的需求的是 Func键<点,双> - 什么是从位置到固定终点的距离?你有什么是 Func键<点,点,双> 。你将如何把你已经钻进你需要什么?随着部分应用程序;你部分应用固定端点作为第一个参数的大致距离的方法,和你走出符合你的寻路算法需要消耗的功能:

  Func键<点,双> distanceFinder = PartiallyApply<点,点,双>(ApproximateDistance,givenEndPoint); 

如果该ApproximateDistance方法已在第一时间被令行禁止:

 静态Func键<点,双> MakeApproximateDistanceFinder(点P1){...} 



那么你就不需要做自己的部分应用程序;你只需要调用 MakeApproximateDistanceFinder 以固定终点,你会做的。

  Func键<点,双> distanceFinder = MakeApproximateDistanceFinder(givenEndPoint); 


I am playing a little bit with functional programming and the various concepts of it. All this stuff is very interesting. Several times I have read about Currying and what an advantage it has.

But I do not get the point with this. The following source demonstrates the using of the curry concept and the solution with linq. Actually, I do not see any advatages of using the currying concept.

So, what is the advantage of using currying?

static bool IsPrime(int value)
{
    int max = (value / 2) + 1;
    for (int i = 2; i < max; i++)
    {
        if ((value % i) == 0)
        {
            return false;
        }
    }
    return true;
}

static readonly Func<IEnumerable<int>, IEnumerable<int>> GetPrimes = 
        HigherOrder.GetFilter<int>().Curry()(IsPrime);

static void Main(string[] args)
{
    int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };

    Console.Write("Primes:");
    //Curry
    foreach (int n in GetPrimes(numbers))
    {
        Console.Write(" {0}", n);
    }
    Console.WriteLine();

    //Linq
    foreach (int n in numbers.Where(p => IsPrime(p)))
    {
        Console.Write(" {0}", n);
    }

    Console.ReadLine();
}

Here is the HigherOrder Filter Method:

public static Func<Func<TSource, bool>, IEnumerable<TSource>, IEnumerable<TSource>> GetFilter<TSource>()
{
    return Filter<TSource>;
}

解决方案

what is the advantage of using currying?

First off, let's clarify some terms. People use "currying" to mean both reformulating a method of two parameters into a methods of one parameter that returns a method of one parameter and partial application of a method of two parameters to produce a method of one parameter. Clearly these two tasks are closely related, and hence the confusion. When speaking formally, one ought to restrict "currying" to refer to the first definition, but when speaking informally either usage is common.

So, if you have a method:

static int Add(int x, int y) { return x + y; }

you can call it like this:

int result = Add(2, 3); // 5

You can curry the 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

Partial application is sometimes also called "currying" when speaking informally because it is obviously related:

Func<int, int> addTwo = y=>Add(2,y);
int result = addTwo(3);

You can make a machine that does this process for you:

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

So now we come to your question:

what is the advantage of using currying?

The advantage of either technique is that it gives you more flexibility in dealing with methods.

For example, suppose you are writing an implementation of a path finding algorithm. You might already have a helper method that gives you an approximate distance between two points:

static double ApproximateDistance(Point p1, Point p2) { ... }

But when you are actually building the algorithm, what you often want to know is what is the distance between the current location and a fixed end point. What the algorithm needs is Func<Point, double> -- what is the distance from the location to the fixed end point? What you have is Func<Point, Point, double>. How are you going to turn what you've got into what you need? With partial application; you partially apply the fixed end point as the first argument to the approximate distance method, and you get out a function that matches what your path finding algorithm needs to consume:

Func<Point, double> distanceFinder = PartiallyApply<Point, Point, double>(ApproximateDistance, givenEndPoint);

If the ApproximateDistance method had been curried in the first place:

static Func<Point, double> MakeApproximateDistanceFinder(Point p1) { ... }

Then you would not need to do the partial application yourself; you'd just call MakeApproximateDistanceFinder with the fixed end point and you'd be done.

Func<Point, double> distanceFinder = MakeApproximateDistanceFinder(givenEndPoint);

这篇关于C#中的LINQ与柯里的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆