Home

Awesome

Fuget Nuget Nuget

Curryfy

Provides strongly typed extensions methods for C# delegates to take advantages of functional programming techniques, like currying and partial application.
Concepts very well known in functional languages like Haskell, F#, Scala, etc.

What and Why?

Curryfy offers strongly typed extensions that lets you take some benefits of functional programming:

Features

Installation

Simply reference Curryfy.dll and you are good to go!

Curryfy is also available via NuGet:

PM> Install-Package Curryfy  

Or visit: https://www.nuget.org/packages/Curryfy

Using the library

All helper methods are available as extension methods under the Curryfy namespace.
They are divided into 7 static classes to avoid method signature ambiguities:

Core concepts

Consider the code snippet below as part of all examples:

Func<int, int, int, int> add = (a, b, c) => a + b + c;

Partial Application

Partial application is the process of pass part of the arguments of a function, returning a function that receives the rest of the arguments. If you provide 1 out of 3 arguments, it'll return a function that takes 2 arguments. If you provide 2 out of 3 arguments, it'll return a function that takes 1 argument.

This feature is available for delegates Func and Action through ApplyPartial extension method.

This method has 1232 overloads.

using static Curryfy.PartialIncrementalFuncExtensions;

var add12 = add.ApplyPartial(5, 7); // add12 is Func<int, int>
var add5 = add.ApplyPartial(5);     // add5 is Func<int, int, int>
var x = add12(3) + add5(7, 3);      // 15 + 15

Note that using the incremental approach, we can only pass the third argument after pass the first and second.
This approach is used by languages like Haskell and F#.
However using the subset approach, we can pass arguments arbitrarily.
You can pass the only first and the third arguments of a function with 5 parameters, for example.

using static Curryfy.PartialSubsetFuncExtensions;

var add3 = add.ApplyPartial(arg3: 3);   // parameter c receives 3
var add10 = add3.ApplyPartial(arg2: 7); // parameter b receives 7
var x = add10(5);                       // parameter a receives 5
Console.WriteLine(x);                   // x = 15

Using the discard approach, we can rely on arguments position instead of name.
This approach is used by languages like Scala.
The previous example using discard approach:

using static Curryfy.PartialDiscardFuncExtensions;
using static Curryfy.Discard;

var add3 = add.ApplyPartial(_, _, 3);   // parameter c receives 3
var add10 = add3.ApplyPartial(_, 7);    // parameter b receives 7
var x = add10(5);                       // parameter a receives 5
Console.WriteLine(x);                   // x = 15

Note: when using C# discard feature in the same scope that discard approach, you should use double underscore (__) instead of single underscore (_) in the method call. That is, instead of sum(_, 3) is sum(__, 3).
If not using in same scope single underscore is fine.

Which one of these 3 approaches fits better depending of situation. For example, if you have a function with 4 parameters and want to pass only the third, might be more interesting to specify the desired argument f(arg3: "foo") rather than use discard f(_, _, "foo", _). In general:

If you want, it is possible to enable more than one approach at the same time, for example:

using static Curryfy.PartialIncrementalFuncExtensions;
using static Curryfy.PartialDiscardFuncExtensions;
using static Curryfy.Discard;

Func<string, char, int, bool> f = (s, c, i) => s[i] == c;

var g = f.ApplyPartial(_, 'b', 1); // using discard approach, g is Func<string, bool>

var h = f.ApplyPartial("ab", 'b'); // using incremental approach, h is Func<int, bool>

Currying

Currying is the process of splitting a function with multiple arguments into a nested chain of one argument functions. Therefore a curried function is a function which takes its arguments one at a time, returning a new function at each step.

This feature is available for Func delegates through Curry extension method.

This method has 15 overloads.

using static Curryfy.CurryExtensions;

var addCurried = add.Curry();   // addCurried is Func<int, Func<int, Func<int, int>>>

var add5 = addCurried(5);       // add5 is Func<int, Func<int, int>>
var add12 = add5(7);            // add12 is Func<int, int>
var x = add12(3);               // x is 15

var y = addCurried(5)(7)(3);    // y is 15

UnCurrying

UnCurrying is the process of transforms a curried function in a function which takes all of its arguments at once.

This feature is available for Func delegates through UnCurry extension method.

This method has 15 overloads.

using static Curryfy.CurryExtensions;

var curried = add.Curry();            // curried is Func<int, Func<int, Func<int, int>>>
var add5 = curried(5);                // add5 is Func<int, Func<int, int>>
var uncurried = add5.UnCurry();       // uncurried is Func<int, int, int>

var x = uncurried(7, 3) + curried(5)(7)(3);    // 15 + 15