Подтвердить что ты не робот

Преобразование 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)?

Спасибо

4b9b3361

Ответ 1

для первой части вы можете даже сделать некоторую "более высокую" функцию порядка:



Func<A,C&gt MapFun<A,B,C&gt(Func<A,B&gt input, Func<B,C&gt 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&gt(this Func<A,B> input, Func<B,C> f)
    {
         return a => f(input(a));
    }
}

вот очень простой тест:


Func<int, string&gt test = i =&gt 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 (но с более сильным синтаксисом).