Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我们需要C#中的不动点组合子吗?_C#_Functional Programming_Lambda - Fatal编程技术网

我们需要C#中的不动点组合子吗?

我们需要C#中的不动点组合子吗?,c#,functional-programming,lambda,C#,Functional Programming,Lambda,我在C#中使用递归lambdas,发现了两种在web上实现这一点的方法。一种方法使用,另一种不使用。在下面的代码中,f1是使用combinator构建的,f2是直接定义的。我的问题是,我们是否需要C#中的定点组合符,或者该语言已经提供了我们所需要的一切,所以我们可以不使用它们 class Program { static Func<T, T> F<T>(Func<Func<T,T>,Func<T,T>> f) {

我在C#中使用递归lambdas,发现了两种在web上实现这一点的方法。一种方法使用,另一种不使用。在下面的代码中,f1是使用combinator构建的,f2是直接定义的。我的问题是,我们是否需要C#中的定点组合符,或者该语言已经提供了我们所需要的一切,所以我们可以不使用它们

class Program
{
    static Func<T, T> F<T>(Func<Func<T,T>,Func<T,T>> f)
    {
        return x => f(F(f))(x);
    }

    static void Main(string[] args)
    {
        Func<Func<int,int>,Func<int,int>> f = fac => x => x == 0 ? 1 : x * fac(x - 1);
        var f1 = F(f);

        Console.WriteLine(f1(5));

        Func<int, int> f2 = null;
        f2 = x => x == 0 ? 1 : x * f2(x - 1);

        Console.WriteLine(f2(5));
    }
}
类程序
{
静态函数F(函数F)
{
返回x=>f(f(f))(x);
}
静态void Main(字符串[]参数)
{
Func f=fac=>x=>x==0?1:x*fac(x-1);
var f1=F(F);
控制台写入线(f1(5));
Func f2=空;
f2=x=>x==0?1:x*f2(x-1);
控制台写入线(f2(5));
}
}

因为我们可以给一个方法命名,这意味着该语言已经具备了对内置递归的必要支持

请注意,问题中给出的第二种方法涉及在引入变量后更改变量的值,使其不是“纯”函数编程。
只有当你的函数演算系统没有一个内置的函数概念,在定义完全定义之前,可以通过名称引用它自己的定义,Y-combinator才是必要的。C#有两种方法可以直接做到这一点:1。最初将函数变量定义为null和2。声明普通命名方法(目前为止是首选技术)。

另一种方法是将递归Func委托声明为静态成员:

static Func<int, int> Factorial = (n) => n <= 1 ? 1 : n*Factorial(n - 1);
static Func Factorial=(n)=>n需要是什么意思?C#不需要它们,因为您不应该在C#中尝试这种函数式编程。这只是一条通往痛苦的道路

记忆递归函数是一个需要定点组合器的地方。将此与中的进行比较


因此,在C#“需要”这一点之前,需要做大量的工作才能使这类编程合理实用

我认为,如果有一个名为Recursive的额外实用程序类,它会非常优雅,如下所示:

public static class Recursive {
            public static Func<R> Func<R>(
                Func<Func<R>, Func<R>> f) { 
                return () => f(Func(f))(); }
            public static Func<T1, R> Func<T1, R>(
                Func<Func<T1, R>, Func<T1, R>> f) { 
                return x => f(Func(f))(x); }
            public static Func<T1, T2, R> Func<T1, T2, R>(
                Func<Func<T1, T2, R>, Func<T1, T2, R>> f) {
                return (a1, a2) => f(Func(f))(a1, a2);
            }
            //And so on...
        }

class Program {

    static void Main(string[] args) {

        Console.WriteLine(
            Recursive.Func<int, int>(factorial =>
                x => x == 0 ? 1 : factorial(x - 1) * x
            ) 
            (10)
        );

        Console.WriteLine(
            Recursive.Func<int,int,int>(gcd =>
                (x,y) => 
                    x == 0 ? y:
                    y == 0 ? x:
                    x > y  ? gcd(x % y, y):
                    gcd(y % x, x)
            )
            (35,21)
        );
    }
}
公共静态类递归{
公共静态函数(
Func f){
return()=>f(Func(f))();}
公共静态函数(
Func f){
返回x=>f(Func(f))(x);}
公共静态函数(
函数(f){
返回(a1,a2)=>f(Func(f))(a1,a2);
}
//等等。。。
}
班级计划{
静态void Main(字符串[]参数){
控制台写入线(
Recursive.Func(阶乘=>
x=>x==0?1:阶乘(x-1)*x
) 
(10)
);
控制台写入线(
Recursive.Func(gcd=>
(x,y)=>
x==0?y:
y==0?x:
x>y?总干密度(x%y,y):
gcd(y%x,x)
)
(35,21)
);
}
}

递归函数的记忆功能又如何呢?我想说,由此产生的丑陋意味着它比手工将记忆功能构建成递归函数更糟糕(这并不难做到完全可重用)。是的,没错。如果你试着做这些,C#会很快变得难看,所以在大多数情况下都是不切实际的。