14

我想我的大脑正在爆炸,试图弄清楚 Funcs ......如果这没有意义,我道歉,现在它对我来说很有意义,但它已经是漫长的一天......

1)假设给你一个函数,它接受 T 并输出一个字符串:

 Func<T, string> 

您能否将其转换为一个接受 T 并基于某种逻辑返回布尔值的函数(在这种情况下,如果返回的字符串为空(String.IsNullOrWhiteSpace)?

 Func<T, bool> 

2)如果给你一个,你能做同样的事情吗?

Expression<Func<T, string>>

并需要将其转换为

Func<T, bool>

根据返回的字符串是否为空(String.IsNullOrWhiteSpace)返回真/假?

谢谢

4

4 回答 4

11

对于第一部分,您甚至可以制作一些“高”阶函数:



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,然后使用上面的代码。请参阅有关 Expression.Compile 的 MSDN 文档

PS:重命名函数以更好地匹配它的意图(它的函数组合)

于 2011-08-21T12:19:13.510 回答
3

你能不能把它定义为一个单独的委托:

Func<T, string> func1 = t => t.ToString();
Func<T, bool> func2 = t => string.IsNullOrEmpty(func1(t));
于 2011-08-21T12:18:40.923 回答
2

对于第一部分,该技术称为函数组合,即您组合 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));
}
于 2011-08-21T12:32:30.110 回答
2

To 1:是(您也可以参数化 bool 和 string):

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))就是你在这里做的。

将 source 视为g:A->B和 map 视为f:B->C(其中 A、B 和 C 是集合),因此结果f . gh:A->C。顺便说一句,.运算符通常内置在函数式编程语言中,例如 Haskell,并实现与您的函数相同的compose功能(但语法更简洁)。

于 2011-08-21T12:33:18.580 回答