33

In the latest version of C#, can I do something like Haskell's function composition? more...?

Function composition is the act of pipelining the result of one function, to the input of another, creating an entirely new function.

I feel like linq is the closest but that's chaining, not function composition, right?

Jay Bazuzi
  • 45,157
  • 15
  • 111
  • 168
Joan Venge
  • 315,713
  • 212
  • 479
  • 689
  • FYI, you can use the `+` operator to combine delegates (functions and actions) so they run in sequence. You can even use `-` to remove a delegate that has been added. It works like event `+=` and `-=` (unless [add and remove have been explicitly defined](https://msdn.microsoft.com/en-us/library/cc713648.aspx)). This isn't function composition, but it's good to know about. – Joey Adams Feb 20 '15 at 15:58
  • 1
    You should include the full question. If that link goes dead, this question will be totally meaningless. – dfeuer Sep 02 '16 at 19:16

8 Answers8

18
public static class Extensions
{
    public static Func<T, TReturn2> Compose<T, TReturn1, TReturn2>(this Func<TReturn1, TReturn2> func1, Func<T, TReturn1> func2)
    {
        return x => func1(func2(x));
    }
}

Usage:

Func<int, int> makeDouble = x => x * 2;
Func<int, int> makeTriple = x => x * 3;
Func<int, string> toString = x => x.ToString();
Func<int, string> makeTimesSixString = toString.Compose(makeDouble).Compose(makeTriple);

//Prints "true"
Console.WriteLine(makeTimesSixString (3) == toString(makeDouble(makeTriple(3))));
Davy8
  • 30,868
  • 25
  • 115
  • 173
14

I did not let the compiler check this, but this should be possible:

public static Func<T3,T1> my_chain<T1, T2, T3>(Func<T2,T1> f1, Func<T3,T2> f2)
{
    return x => f2(f1(x));
}
ChaosPandion
  • 77,506
  • 18
  • 119
  • 157
Doc Brown
  • 19,739
  • 7
  • 52
  • 88
  • 3
    +1 Now this is a generally useful implementation. I'd swap the types to stay in order though: `Func compose(Func f, Func g) { return (x => f(g(x))) }`. –  Mar 10 '11 at 18:41
  • +1 For showing it's "possible": usually not "practical" in C# though, IMOHO. I generally end up "hand rolling" these in anons as the signatures are usually much more complex in the desired partial application. –  Mar 10 '11 at 18:45
  • Only for functions f1 that have a single parameter. While I can see that in Haskell the equivalent notation is quite strange, I think the lambda notation of C# is "natural" enough that it's better to directly use it. – xanatos Mar 10 '11 at 18:45
  • @xanatos What -- *your* functions have more than one parameter? (Isn't this just in keeping with the spirit of the link? Haskell functions only have one parameter ;-) –  Mar 10 '11 at 18:47
  • @xanatos: Yes. If you find a meaningful way to deal with them, and convince everyone to settle for that way, feel free to add overloads. So far, function composition (as used in functional programming, dunno about math) is generally only defined for two unary functions. –  Mar 10 '11 at 18:48
  • 2
    @pst Sadly I'm quite sure more than half of the "standard" methods of .NET have more than one parameter. Those bad persons at Microsoft created a truly hellish framework! They should have learned for Haskell! One parameter is enough for everybody!! :-) – xanatos Mar 10 '11 at 18:49
  • 1
    @delnan And if there is a controversy if Scala fits as a "functional language" ... C# sure doesn't ;-) –  Mar 10 '11 at 18:50
  • @xanatos It's not how many parameters are "taken" (e.g. shown in the API documentation), but rather how the parameters are applied. In Haskell parameters are applied one by one by one where each intermediate application results in another function (taking one parameter at most). The syntax hides the tedious mechanics. But an entirely different language/runtime... –  Mar 10 '11 at 18:53
  • @xanatos: Haskell functions are curried, so they can take as many arguments as they like (because, indeed, 1 argument really isn't enough for many purposes) but still be still unary as far as the type system is concerned (you lose overloading and optional parameters though, and varargs harder - but that's a different story). –  Mar 10 '11 at 18:55
  • @delnan, how can Haskell take as many args as possible? Is it like C# params args thing? – Joan Venge Mar 10 '11 at 19:04
  • @Doc Brown: Is this generic version supposed to support any type to any type? – Joan Venge Mar 10 '11 at 19:06
  • 2
    @Joan: Basically, `f x y z = (x + y) * z` becomes `f x = (\y -> (\z -> ))`. So for each parameter you apply, you get a closure that's one step/parameter closer to the actual result, but will wait for the remaining arguments before calculating the result. Also goes by the term "partial application". You can do it yourself in every language that supports closures, but it's only practical with language assistance. –  Mar 10 '11 at 19:11
  • @delnan, thanks for explaining. I don't think I know about closures. Does C# support it? – Joan Venge Mar 10 '11 at 19:14
  • 1
    @Joan Venge a [Closure](http://en.wikipedia.org/wiki/Closure_%28computer_programming%29) is a [often anonymous] function that binds over a free variable: `var limit = 100; elms.Where(x => x > limit);` <-- the lambda `x => x > limit` is a closure here as it "binds" to `limit` from the enclosing scope. I think the "old" inline delegate syntax could also create closures, but I'm not sure as I've never been restricted to C#2 ;-) –  Mar 10 '11 at 20:16
  • @pst, thanks I see what you mean now. Didn't realize those were closures. But this closure thing sounds like something the compiler, etc needs to make it work, right? It isn't something that benefits the developer? The closure itself, not the end effect. – Joan Venge Mar 10 '11 at 20:27
  • 1
    @Joan Venge It needs to be a defined part of the language -- compilers just implement languages :) I find it (closures and lambdas) *very* beneficial to me: ever try to "filter" a List in Java? Without closures some very simple tasks become stupidly tedious. Some might argue that without function composition and implicit currying some simple tasks become stupidly tedious -- but C# is C# and not Haskell or Java (thankfully on this last!) ;-) –  Mar 10 '11 at 20:38
  • can someone show a practical application of this function? – Alex Gordon Feb 01 '17 at 02:42
12

There is no specific operator / "syntax sugar" for that in C# (however, in F# you would use the >> operator).

There is a great blog post on this subject from Matthew Podwysocki. He suggests this kind of construct in C#:

public static class FuncExtensions
{
    public static Func<TSource, TResult> ForwardCompose<TSource, TIntermediate, TResult>(
        this Func<TSource, TIntermediate> func1, Func<TIntermediate, TResult> func2)
    {
        return source => func2(func1(source));
    }
}

Func<Func<int, int>, IEnumerable<int>, IEnumerable<int>> map = (f, i) => i.Select(f);
Func<Func<int, bool>, IEnumerable<int>, IEnumerable<int>> filter = (f, i) => i.Where(f);
Func<int, Func<int, int, int>, IEnumerable<int>, int> fold = (s, f, i) => i.Aggregate(s, f);

// Compose together
var mapFilterFold = map.Apply(x => x * x * x)
    .ForwardCompose(filter.Apply(x => x % 3 == 0))
    .ForwardCompose(fold.Apply(1, (acc, x) => acc * x));
Console.WriteLine(mapFilterFold(Enumerable.Range(1, 10)));
Maxim Gueivandov
  • 2,370
  • 1
  • 20
  • 33
7

C# doesn't have first class support but it's not particularly hard to implement. You just have to write a lot of overloads.

public static class Composition
{
    public static Func<T2> Compose<T1, T2>(Func<T1> f1, Func<T1, T2> f2)
    {
        return () => f2(f1());
    }

    public static Func<T1, T3> Compose<T1, T2, T3>(Func<T1, T2> f1, Func<T2, T3> f2)
    {
        return v => f2(f1(v));
    }
}
ChaosPandion
  • 77,506
  • 18
  • 119
  • 157
4

It's not nearly as pretty, but you could do:

Func<IEnumerable<T>, IEnumerable<T>> desort = l => l.OrderBy(i => i).Reverse();

Or, if you want something more composit-y (that acts on the array in place):

Action<int[]> desort = a => Array.Reverse(Array.Sort(a));

Assuming those methods existed...but the syntax should be about right.

You could then use it in the following way (assuming you went with the first method above):

var arr = { 2,8,7,10,1,9,5,3,4,6 };
var desortedArr = desort(arr);
Justin Niessner
  • 242,243
  • 40
  • 408
  • 536
  • @delnan - That's correct, but this is definitely the way composition is typically handled in C# (since it's not built in to the language). – Justin Niessner Mar 10 '11 at 18:37
  • Sort isn't chainable for Lists (it's void), but OrderBy(p => p) is (it's a small detail), the idea/example are correct – xanatos Mar 10 '11 at 18:41
3

More than Linq, it's delegates, and lambda expressions/statements that are similar to chaining.

Func<int, string> a = p => p.ToString();
Func<string, string> b = p => "|" + p + "|";

Func<int, string> c = p => b(a(p));

The definition given in the link is:

Function composition is the act of pipelining the result of one function, to the input of another, creating an entirely new function.

And c is clearly a new function that chain call a and b.

Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
xanatos
  • 109,618
  • 12
  • 197
  • 280
  • 3
    -1 Might be a valueable comment, but doesn't even touch the actual question. Edit: Okay, now you added a hand-rolled composition. So your answer is "No, you have to compose yourself"? –  Mar 10 '11 at 18:32
  • 1
    @delnan Pink fairies don't compose functions in the link given. In the link it's desort = (reverse . sort), in C# it's desort = p => reverse(sort(p)). I can't see the difference (other than the fact that in the example the types are automatically discovered) – xanatos Mar 10 '11 at 18:35
  • 2
    The Haskell equivalent to your code is `(\p -> reverse (sort p))`. It's obvious C#, as any other language that has lambdas, allows you to write an equivalent lambda by hand. The beauty of `(.)` in Haskell etc. is that you don't have do that, you just write the two functions you want to compose. –  Mar 10 '11 at 18:37
  • @delnan: What is the actual question? I don't understand it if this answer doesn't touch it. – Gabe Mar 10 '11 at 18:38
  • @Gabe: It used to be the first sentence alone. –  Mar 10 '11 at 18:38
  • 1
    I had pressed the wrong key and the response was sent... I was still editing it. – xanatos Mar 10 '11 at 18:39
1

No, not short of defining your own generic Compose<T, U...>() functions. C# has no built-in functionality to help you out with this. (It doesn't do partial application, either.)

mqp
  • 70,359
  • 14
  • 95
  • 123
0

Example for function composition in C#

f(x) ° g(x)

Func<int, int> f = x => x + 2;
Func<int, int> g = x => 3 * x;

Func<int, int> b = x => f(g(x));

int result = b(2); //Result is 8
Tim Hovius
  • 721
  • 6
  • 16