Est-ce que c# supporte la composition des fonctions?

dans la dernière version de C#, puis-je faire quelque chose comme ?

j'ai l'impression que linq est le plus proche, mais c'est de l'enchaînement, pas de la composition fonctionnelle, pas vrai?

24
demandé sur Joan Venge 2011-03-10 21:29:53
la source

8 ответов

Je n'ai pas laissé le compilateur vérifier cela, mais cela devrait être possible:

Func<T3,T1> my_chain(Func<T2,T1> f1, Func<T3,T2> f2)
{
    return (x=> f2(f1(x)));
}
13
répondu Doc Brown 2011-03-10 21:36:29
la source
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));
    }
}

Utilisation:

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))));
14
répondu Davy8 2011-03-10 21:59:21
la source

il n'y a pas d'opérateur spécifique / "sucre de syntaxe" pour cela en C# (Cependant, en F# vous utiliserez le >> opérateur).

excellent blog post sur ce sujet de Matthew Podwysocki. Il suggère ce genre de construction en 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)));
9
répondu Maxim Gueivandov 2011-03-10 21:50:48
la source

C# n'a pas de support de première classe mais il n'est pas particulièrement difficile à mettre en œuvre. Tu dois juste écrire beaucoup de surcharges.

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));
    }
}
6
répondu ChaosPandion 2011-03-10 22:13:18
la source

Il n'est pas aussi joli, mais tu pourrais faire:

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

Ou, si vous voulez quelque chose de plus composit-y (qui agit sur le réseau en place):

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

en Supposant que ces méthodes existaient...mais la syntaxe devrait être sujet de droit.

vous pouvez alors l'utiliser de la manière suivante (en supposant que vous avez utilisé la première méthode ci-dessus):

var arr = { 2,8,7,10,1,9,5,3,4,6 };
var desortedArr = desort(arr);
4
répondu Justin Niessner 2011-03-10 21:42:20
la source

plus que Linq, ce sont les délégués, et lambda expressions/déclarations qui sont similaires à l'enchaînement.

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

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

La définition donnée dans le lien est:

la composition fonctionnelle est l'action de Pipeliner le résultat d'une fonction, à l'entrée d'une autre, créant une fonction entièrement nouvelle.

Et c est clairement une nouvelle fonction qui fait appel à la chaîne a et b.

3
répondu xanatos 2011-03-20 00:44:26
la source

non, pas à court de définir votre propre générique Compose<T, U...>() fonctions. C# n'a pas de fonctionnalité pour vous aider avec ceci. (Il ne fait pas d'application partielle, non plus.)

2
répondu mquander 2011-03-10 21:39:45
la source

exemple de composition de fonction en 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
1
répondu Tim Hovius 2016-06-11 11:54:27
la source

Autres questions sur