Композиция функций - PullRequest
       0

Композиция функций

8 голосов
/ 04 января 2012

Ниже функции 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)); }

Вот пара простых Func значений, которые можно составить:

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

Func<int, int> mod_by_2 = x => { return x % 2; };

например. это работает:

Console.WriteLine(Compose(is_zero, mod_by_2)(4));

Однако, если вместо этого у меня есть эти эквивалентные статические методы:

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

static int ModBy2(int n) { return n % 2; }

тот же пример не работает с ними. То есть это приводит к ошибке времени компиляции:

Console.WriteLine(Compose(IsZero, ModBy2)(4));

Явная передача типов в Compose устраняет проблему:

Console.WriteLine(Compose<bool, int, int>(IsZero, ModBy2)(4));

Можно ли написать Compose так, чтобы оно работало со статическими методами без явных типов?

Это хороший подход к реализации Compose? Кто-нибудь может сделать улучшения для этого?

1 Ответ

10 голосов
/ 04 января 2012

Проблема здесь не в использовании static методов, а в использовании групп методов. Когда вы используете имя функции в качестве выражения, не вызывая его, тогда это группа методов и должна пройти преобразование группы методов. У вас точно такая же проблема с методами экземпляра.

Проблема, с которой вы сталкиваетесь, заключается в том, что C # не может сделать вывод типа возврата для групп методов. Использование Compose(IsZero, ModBy2)) требует, чтобы тип возвращаемого значения выводился как для IsZero, так и ModBy2, и, следовательно, эта операция не выполняется.

Это известное ограничение возможностей вывода компилятора C #. Эрик Липперт написал обширную статью в блоге на эту конкретную тему, которая подробно описывает эту проблему

...