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.
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:
public static M<V> Bind<U, V>(this M<U> m, Func<U, M<V>> k)
and
public static M<T> Unit<T>(this T value)
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:
http://blogs.msdn.com/b/wesdyer/archive/2008/01/11/the-marvels-of-monads.aspx
To answer your actual question:
Are these already in the .net library?
Those exact functions are not in the framework. But functions very much like those exist in the framework. For example, SelectMany
on IEnumerable<T>
is analogous to your To
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
Help a C# developer understand: What is a monad?
You can use Lazy to lazy-load values.
Lazy<int> lazy = new Lazy<int>(() => delayEvaluatingMe());
int delayed = lazy.Value;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With