Преобразование Func <T, String> в Func <T, bool>
Я думаю, что мой разум взрывается, пытаясь выяснить, какие Funcs... Если это не имеет смысла, я извиняюсь, сейчас это имеет смысл для меня, но это был уже долгий день.
1) Предполагая, что вам задан func, который принимает T и выводит строку:
Func<T, string>
Можете ли вы преобразовать это в func, который принимает T и возвращает bool на основе некоторой логики (в этом случае, если возвращаемая строка пуста (String.IsNullOrWhiteSpace)?
Func<T, bool>
2) Можете ли вы сделать то же самое, если вам дано
Expression<Func<T, string>>
и нужно преобразовать его в
Func<T, bool>
который возвращает true/false на основании, если возвращаемая строка пуста (String.IsNullOrWhiteSpace)?
Спасибо
Ответы
Ответ 1
для первой части вы можете даже сделать некоторую "более высокую" функцию порядка:
Func<A,C> MapFun<A,B,C>(Func<A,B> input, Func<B,C> transf)
{
return a => transf(input(a));
}
используйте
Func <T,string> test = ...
var result = MapFun(test, String.IsNullOrWhiteSpace);
(Я надеюсь, что здесь используется тип типа типа С#)
Если вы определяете это как расширение в Func, это становится еще проще:
public static class FuncExtension
{
public static Func<A,C> ComposeWith<A,B,C>(this Func<A,B> input, Func<B,C> f)
{
return a => f(input(a));
}
}
вот очень простой тест:
Func<int, string> test = i => i.ToString();
var result = test.ComposeWith(string.IsNullOrEmpty);
Для второго: я думаю, вы можете скомпилировать выражение в "реальный" Func, а затем использовать приведенный выше код. см. Документы MSDN для Expression.Compile
PS: переименована функция для лучшего соответствия ее намерению (ее составная функция)
Ответ 2
Не можете ли вы определить его как отдельный делегат:
Func<T, string> func1 = t => t.ToString();
Func<T, bool> func2 = t => string.IsNullOrEmpty(func1(t));
Ответ 3
В первой части техника называется композицией функций. Вы составляете 2 функции для создания новой функции.
В вашем случае у вас есть функция Func<T,String>
и другая функция (например, строка пустая или нулевая), которая имеет тип Func<string,bool>
, используя композицию функций, вы можете скомпоновать эти две функции для создания новой функции типа Func<T,Bool>
В большинстве функциональных языков программирования этот состав функции уже определен в их стандартной библиотеке или на самом языке. Но нетрудно создать его для вашего языка, если язык поддерживает функции как значения первого класса.
В С# вы можете использовать следующую функцию, которая позволит вам создавать функции:
public static Func<X,Z> Compose<X,Y,Z>(Func<X,Y> a, Func<Y,Z> b)
{
return (v) => b(a(v));
}
Ответ 4
В 1: Да (вы также можете параметризовать bool и строку):
Func<T, bool> Compose<T>(Func<T, string> source, Func<string, bool>map)
{
return x => map(source(x));
}
To 2: Да, но сначала нужно скомпилировать выражение:
Func<T, bool> Compose<T>(Expression<Func<T, string>> source, Func<string, bool> map)
{
return x => compose(source.Compile(), map)
}
.Compile
скомпилирует выражение в динамический метод CLR, который вы можете вызвать с возвращенным делегатом.
Вы можете использовать этот код следующим образом:
Func<int, string> ts = i => i.ToString();
var result = Compose(ts, string.IsNullOrEmpty);
Кстати, в этом случае вы должны действительно написать функцию более высокого порядка. То, что вы здесь делаете (алгебраически), составляет моноиды. Помните состав функции? f . g := f(g(x))
- это то, что вы здесь делаете.
Подумайте о источнике как g:A->B
и оставьте его как f:B->C
(где A, B и C - множества), поэтому результат f . g
равен h:A->C
. Кстати, оператор .
часто встроен в языки функционального программирования, такие как Haskell, и выполняет ту же функцию, что и ваша функция compose
(но с более сильным синтаксисом).