Convert Func<T, String> to Func<T, bool>

不想你离开。 提交于 2019-12-04 23:45:41
Carsten

for the first part you can even make some "higher"-order function:



Func<A,C&gt MapFun<A,B,C&gt(Func<A,B&gt input, Func<B,C&gt transf)
{
   return a => transf(input(a));
}

use with



Func <T,string> test = ...
var result = MapFun(test, String.IsNullOrWhiteSpace);

(I hope C# type type inference is working here)

If you define this as extension on Func it gets even easier:


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));
    }
}

here is a very simple test:


Func<int, string&gt test = i =&gt i.ToString();
var result = test.ComposeWith(string.IsNullOrEmpty);

For the second one: I think you can compile the expression into a "real" Func and then use the above code. see MSDN Docs on Expression.Compile

PS: renamed the function to better match it's intend (it's function composition)

Could you not define it as a separate delegate:

Func<T, string> func1 = t => t.ToString();
Func<T, bool> func2 = t => string.IsNullOrEmpty(func1(t));

For the first part the technique is known as function composition i.e you compose 2 functions to create a new function. In your case you have a function Func<T,String> and another function (like string empty or null) which is of type Func<string,bool>, using function composition you can compose these two functions to create a new function of type Func<T,Bool>

Most functional programming language have this composition of function already defined in their standard library or in the language itself. But it is no tough to create one for your language if the language supports functions as first class values.

In C# you can use the below function which will allow you to compose functions:

public static Func<X,Z> Compose<X,Y,Z>(Func<X,Y> a, Func<Y,Z> b)
{
    return (v) => b(a(v));
}

To 1: Yes (You can also parametrize bool and string):

Func<T, bool> Compose<T>(Func<T, string> source, Func<string, bool>map)
{
    return x => map(source(x));
}

To 2: Yes, but you need to compile the expression first:

Func<T, bool> Compose<T>(Expression<Func<T, string>> source, Func<string, bool> map)
{
    return x => compose(source.Compile(), map)
}

.Compile will compile the expression into a dynamic CLR method that you can invoke with the returned delegate.

You can use this code like this:

Func<int, string> ts = i => i.ToString();
var result = Compose(ts, string.IsNullOrEmpty);

By the way, in this case you should really write a higher-order function. What you are doing here (algebraically) is composing monoids. Remember function composition? f . g := f(g(x)) is what you are doing here.

Think of source as g:A->B and map as f:B->C (where A,B and C are sets) so the result of f . g is h:A->C. By the way, the . operator is often build into functional programming languages, such as Haskell and achieves the same thing as your compose function (but with cleaner syntax).

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!