将 Func<T, String> 转换为 Func<T, bool>

14
我认为我的头脑已经快要爆炸了,尝试理解Funcs...如果这没有意义,我道歉,现在它对我来说有意义,但今天已经很长时间了....
1)假设您得到一个接受T并输出字符串的函数:
 Func<T, string> 

你能将其转化成一个函数,该函数接受一个T类型的参数,并根据某些逻辑返回一个布尔值吗?(在这种情况下,如果返回的字符串为空(String.IsNullOrWhiteSpace),则返回true)?
 Func<T, bool> 

2) 如果给你一个

,你能做同样的事情吗?

Expression<Func<T, string>>

并且需要将它转换为

Func<T, bool>

请问是否有一个基于返回字符串是否为空的true/false值的方法(String.IsNullOrWhiteSpace)?

谢谢

4个回答

13

对于第一部分,你甚至可以创建一些“高阶”函数:



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

我希望C#类型推断在这里可用。

如果你将它定义为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:将函数重命名以更好地匹配其意图(它是函数组合)。

我猜你是指“类型推断”,而不是“类型干扰” ;) - Yann Trevin
谢谢!看完你的答案后,一切都很清楚。有多个正确答案,但你的是第一个且完整,所以你得到了勾勾。感谢大家! - Peter

3

你可否不把它定义成一个独立的委托:

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

2

对于第一部分,技术被称为函数组合,即将两个函数组合成一个新的函数。

在您的情况下,您有一个类型为 Func<T,String>的函数和另一个函数(例如字符串为空或null),其类型为 Func<string,bool>,使用函数组合,您可以将这两个函数组合成一个类型为 Func<T,Bool>的新函数。

大多数函数式编程语言已经在它们的标准库中或语言本身中定义了函数的组合。但是,如果语言支持函数作为一级值,则创建一个函数用于您的语言并不难。

在C#中,您可以使用以下函数来允许您组合函数:

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

2
对于问题1:是的(你也可以对布尔值和字符串进行参数化)。
Func<T, bool> Compose<T>(Func<T, string> source, Func<string, bool>map)
{
    return x => map(source(x));
}

对于第二个问题,是的,但您需要先编译表达式:

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函数相同的功能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接