Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there already built in functional C#/.NET constructs like these? g(h()), or

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.

like image 301
lucidquiet Avatar asked Jan 23 '12 19:01

lucidquiet


2 Answers

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?

enter image description here

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?

like image 91
Eric Lippert Avatar answered Sep 23 '22 05:09

Eric Lippert


You can use Lazy to lazy-load values.

Lazy<int> lazy = new Lazy<int>(() => delayEvaluatingMe());
int delayed = lazy.Value;
like image 45
Bort Avatar answered Sep 22 '22 05:09

Bort