是否已经内置了类似这样的功能性 C#/.NET 结构? g(h()),或
public static Func<V> To<T, V>(this Func<T> g, Func<T, V> h)
{
return () => h(g());
}
public static Func<T> ToIdentity<T>(this T t)
{
return () => t;
}
我有时在延迟评估时会使用这些和其他方法。这些已经在 .net 库中了吗?
编辑:
这是一个示例用法:
public static string SuffixColumn(this string v, string suffix, int columns)
{
return
v.ToIdentity()
.ToScrubbedHtml()
.ToFormat(() => "{0} " + suffix.ToLower().PadLeft(columns, ' '))
.ToErrorText(v, suffix, columns)();
}
ToErrorText 检查“v”是否合法(非错误代码、非空等),如果好则运行 Func 中的链接,如果坏则产生失败 -安全文本结果。如果 v、后缀或列不好,则永远不会调用 ToFormat。 (因此延迟/未评估使用)。
ToFormat 几乎是提供的 Func 和 string.Format 的组合。 ToIdentity 用于将 v 提升为 Func,然后链中的所有内容都基于 T 的某个 Func。
public static Func<V> To<T, V>(this Func<T> g, Func<T, V> h)
{
return () => h(g());
}
public static Func<T> ToIdentity<T>(this T t)
{
return () => t;
}
I sometimes use these and others when delaying evaluation. Are these already in the .net library?
Edit:
Here is an example usage:
public static string SuffixColumn(this string v, string suffix, int columns)
{
return
v.ToIdentity()
.ToScrubbedHtml()
.ToFormat(() => "{0} " + suffix.ToLower().PadLeft(columns, ' '))
.ToErrorText(v, suffix, columns)();
}
ToErrorText checks 'v' as legitimate (non-error code, non-null, etc), if good it runs the chained in Func, if bad it produces fail-safe text result. If v, suffix, or columns are not good then ToFormat will never be called. (Hence the delayed/non-evaluated usage).
ToFormat is nearly the composition of the provided Func and string.Format. ToIdentity is used to lift v to a Func and then everything in the chain is based on some Func of T.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
让我看看我是否理解:您正在使用 lambda 来捕获“包装”对象(一个
Func
)中的值,然后围绕包装对象构建延迟评估函数的工作流程, 是的?虽然用函数构建它是可行的,但我个人倾向于用某种自定义类型构建 monad ;似乎很容易将作用于单子类型或其“底层”类型的函数与单子本身的实例混为一谈。您基本上是使用函数构建身份单子;我更倾向于简单地创建一个类或接口,其名称反映您放置身份单子的目的。
您还可以考虑重命名您的方法。您的“To”传统上称为“Bind”,您的“ToIdentity”传统上称为“Unit”。
也就是说,monad 类型
M
的 monad 模式通常具有以下方法:和
绑定允许您在 monad 上实现函数组合,类似于在“底层”上组合的函数单子的类型。
有关 C# 中 monad 奇迹的简单介绍,请参阅我以前的同事 Wes Dyer 关于该主题的精彩文章:
https://learn.microsoft.com/en-us/archive/blogs/wesdyer/the-marvels-of-monads
回答您的实际问题:
这些确切的功能不在框架中。但功能与框架中存在的功能非常相似。例如,
IEnumerable
上的SelectMany
类似于您的To
方法;它实现了序列上的一元绑定操作。new Nullable(123)
类似于您的“ToIdentity”方法;它实现了“也许单子”的单子单元操作。等等。CLR 类型系统不够丰富,无法表达一般的 monad 模式;为此,您需要一个“更高”的类型系统,例如 Haskell。您必须自己构建每个特定的单子。不过,看起来您进展顺利。
关于在类似 C# 的语言中使用 monad 的更多想法:
C# 中的 Monad——为什么 Bind 实现需要传递函数来返回 monad?
Monad 用简单的英语吗? (对于没有 FP 背景的 OOP 程序员)
为什么没有像 IMonad这样的东西在即将推出的 .NET 4.0 中
在 C# 中,什么是一个单子?
Let me see if I understand: you are using lambdas to capture values in a "wrapper" object -- a
Func<T>
-- and then build a workflow of lazily-evaluated functions around the wrapped object, yes?Though building it out of functions works, I would personally be inclined to build the monad out of some custom type; it seems too easy to conflate functions that act on the monadic type or its "underlying" type with instances of the monad itself. You are basically building the identity monad using functions; I'd be more inclined to simply create a class or interface with a name that reflects the purpose to which you are putting the identity monad.
You might also consider renaming your methods. Your "To" is traditionally called "Bind" and your "ToIdentity" is traditionally called "Unit".
That is, a monad pattern for a monad type
M<T>
usually has the methods:and
The bind allows you to implement composition of functions on monads that are analogous to functions that compose on the "underlying" types of the monads.
For a gentle introduction to the marvels of monads in C#, see my erstwhile coworker Wes Dyer's great article on the subject:
https://learn.microsoft.com/en-us/archive/blogs/wesdyer/the-marvels-of-monads
To answer your actual question:
Those exact functions are not in the framework. But functions very much like those exist in the framework. For example,
SelectMany
onIEnumerable<T>
is analogous to yourTo
method; it implements the monadic bind operation on sequences.new Nullable<int>(123)
is analogous to your "ToIdentity" method; it implements the monadic unit operation for the "maybe monad". And so on.The CLR type system is insufficiently rich to express the monad pattern in general; for that you need a "higher" type system, like that of Haskell. You'll have to build each specific monad yourself. However, it looks like you are well on your way.
Some more thoughts on using monads in C#-like languages:
Monads in C# -- why Bind implementations require passed function to return a monad?
Monad in plain English? (For the OOP programmer with no FP background)
Why there is no something like IMonad<T> in upcoming .NET 4.0
In C#, What is a monad?
您可以使用 Lazy 来延迟加载值。
You can use Lazy to lazy-load values.