功能构成

dha*_*ech 9 c# functional-programming

Compose功能下面.如果是f并且g是返回值的一元函数,则Compose(f,g)返回一个函数,该函数在被调用时x执行等价于f(g(x)).

static Func<X, Z> Compose<Z, Y, X>(Func<Y, Z> f,Func<X, Y> g) 
{ return x => f(g(x)); }
Run Code Online (Sandbox Code Playgroud)

这里有几个简单的Func值可以组成:

Func<int, bool> is_zero = x => { return x == 0; };

Func<int, int> mod_by_2 = x => { return x % 2; };
Run Code Online (Sandbox Code Playgroud)

这有效:

Console.WriteLine(Compose(is_zero, mod_by_2)(4));
Run Code Online (Sandbox Code Playgroud)

但是,如果我改为使用这些等效的静态方法:

static bool IsZero(int n) { return n == 0; }

static int ModBy2(int n) { return n % 2; }
Run Code Online (Sandbox Code Playgroud)

同样的例子不适用于那些.即这会产生编译时错误:

Console.WriteLine(Compose(IsZero, ModBy2)(4));
Run Code Online (Sandbox Code Playgroud)

明确传递类型以Compose解决问题:

Console.WriteLine(Compose<bool, int, int>(IsZero, ModBy2)(4));
Run Code Online (Sandbox Code Playgroud)

反正有Compose没有显式类型的静态方法?

这是一个很好的实施方法Compose吗?任何人都可以对此进行改进吗?

Jar*_*Par 10

这里的问题不是使用static方法而是使用方法组.当您使用函数名作为表达式而不调用它时,它是一个方法组,必须通过方法组转换.你会遇到与实例方法完全相同的问题.

您遇到的问题是C#无法对方法组进行返回类型推断.使用Compose(IsZero, ModBy2))需要返回类型推断两个IsZeroModBy2,因此此操作将失败.

这是C#编译器的推理功能的已知限制.Eric Lippert写了一篇关于这个特定主题的博客文章,详细介绍了这个问题

  • 我注意到这篇文章有点过时了.在这种特殊情况下,它是正确的; 你不能对方法组进行推理,因为我们有鸡蛋问题; 在知道从方法组中选择什么方法之前,我们无法确定委托类型是什么,并且在知道委托*形式参数*类型之前我们不能对方法组执行重载解析.相反,如果推断了委托*返回类型*但*形式参数类型*都以某种方式已知,那么返回类型推断将适用于方法组. (4认同)
  • @dharmatech:当然有一个很好的理由.如果我们在方法组中只有一个方法的情况下有一个重载分辨率算法,并且如果有两个完全不同的*算法,那将是奇怪的*.例如,这意味着*为程序添加新的明确重载可能导致它无法编译*.更一般地说,制作一种语言,要求其编译器推理*所有可能的逻辑推理*不是我们的目标; 制作具有*清晰且一致的规则*的语言是一个目标. (4认同)